mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-10 14:15:51 +00:00
Compare commits
8 Commits
Bronek/cte
...
Bronek/Int
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99693a10c8 | ||
|
|
cb4e9bd5c8 | ||
|
|
23372d348f | ||
|
|
2e152216ef | ||
|
|
bed7f1f618 | ||
|
|
a0800e3845 | ||
|
|
375635528e | ||
|
|
55d5655ff3 |
7
.github/scripts/rename/cmake.sh
vendored
7
.github/scripts/rename/cmake.sh
vendored
@@ -74,19 +74,16 @@ if grep -q '"xrpld"' cmake/XrplCore.cmake; then
|
||||
# The script has been rerun, so just restore the name of the binary.
|
||||
${SED_COMMAND} -i 's/"xrpld"/"rippled"/' cmake/XrplCore.cmake
|
||||
elif ! grep -q '"rippled"' cmake/XrplCore.cmake; then
|
||||
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake > cmake.tmp
|
||||
ghead -n -1 cmake/XrplCore.cmake > cmake.tmp
|
||||
echo ' # For the time being, we will keep the name of the binary as it was.' >> cmake.tmp
|
||||
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >> cmake.tmp
|
||||
tail -1 cmake/XrplCore.cmake >> cmake.tmp
|
||||
mv cmake.tmp cmake/XrplCore.cmake
|
||||
fi
|
||||
|
||||
# Restore the symlink from 'xrpld' to 'rippled'.
|
||||
${SED_COMMAND} -i -E 's@create_symbolic_link\(xrpld@create_symbolic_link(rippled@' cmake/XrplInstall.cmake
|
||||
|
||||
# Remove the symlink that previously pointed from 'ripple' to 'xrpl' but now is
|
||||
# no longer needed.
|
||||
${SED_COMMAND} -z -i -E 's@install\(CODE.+CMAKE_INSTALL_INCLUDEDIR}/xrpl\)\n"\)\n+@@' cmake/XrplInstall.cmake
|
||||
${SED_COMMAND} -z -i -E 's@install\(CODE.+CMAKE_INSTALL_INCLUDEDIR}/xrpl\)\n"\)@install(CODE "set(CMAKE_MODULE_PATH \\"${CMAKE_MODULE_PATH}\\")")@' cmake/XrplInstall.cmake
|
||||
|
||||
popd
|
||||
echo "Renaming complete."
|
||||
|
||||
2
.github/scripts/strategy-matrix/generate.py
vendored
2
.github/scripts/strategy-matrix/generate.py
vendored
@@ -138,6 +138,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# Unity on linux/amd64
|
||||
if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-15' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64':
|
||||
cmake_args = f'-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0 {cmake_args}'
|
||||
cmake_target = 'coverage'
|
||||
build_only = True
|
||||
|
||||
# Generate a unique name for the configuration, e.g. macos-arm64-debug
|
||||
# or debian-bookworm-gcc-12-amd64-release-unity.
|
||||
|
||||
186
.github/workflows/reusable-build-test-config.yml
vendored
186
.github/workflows/reusable-build-test-config.yml
vendored
@@ -7,23 +7,19 @@ on:
|
||||
description: "The directory where to build."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
build_only:
|
||||
description: 'Whether to only build or to build and test the code ("true", "false").'
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
build_type:
|
||||
description: 'The build type to use ("Debug", "Release").'
|
||||
type: string
|
||||
required: true
|
||||
|
||||
cmake_args:
|
||||
description: "Additional arguments to pass to CMake."
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
cmake_target:
|
||||
description: "The CMake target to build."
|
||||
type: string
|
||||
@@ -33,7 +29,6 @@ on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
@@ -56,162 +51,27 @@ on:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
ENABLED_VOIDSTAR: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
ENABLED_COVERAGE: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }}
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
build:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
cmake_args: ${{ inputs.cmake_args }}
|
||||
cmake_target: ${{ inputs.cmake_target }}
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
image: ${{ inputs.image }}
|
||||
config_name: ${{ inputs.config_name }}
|
||||
nproc_subtract: ${{ inputs.nproc_subtract }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||
with:
|
||||
disable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
uses: ./.github/actions/build-deps
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
|
||||
- name: Build the binary
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Upload rippled artifact (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
path: ${{ env.BUILD_DIR }}/rippled
|
||||
retention-days: 3
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Check linking (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
shell: bash
|
||||
run: |
|
||||
ldd ./rippled
|
||||
if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
|
||||
echo 'The binary is statically linked.'
|
||||
else
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify presence of instrumentation (Linux)
|
||||
if: ${{ runner.os == 'Linux' && env.ENABLED_VOIDSTAR == 'true' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
shell: bash
|
||||
run: |
|
||||
./rippled --version | grep libvoidstar
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
# Windows locks some of the build files while running tests, and parallel jobs can collide
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
|
||||
shell: bash
|
||||
run: |
|
||||
ctest \
|
||||
--output-on-failure \
|
||||
-C "${BUILD_TYPE}" \
|
||||
-j "${PARALLELISM}"
|
||||
|
||||
- name: Prepare coverage report
|
||||
if: ${{ !inputs.build_only && env.ENABLED_COVERAGE == 'true' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
shell: bash
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target coverage
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.ENABLED_COVERAGE == 'true' }}
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: ${{ inputs.build_dir }}/coverage.xml
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
- name: Run the embedded tests
|
||||
if: ${{ !inputs.build_only && env.ENABLED_COVERAGE != 'true' }}
|
||||
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', inputs.build_dir, inputs.build_type) || inputs.build_dir }}
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
./rippled --unittest --unittest-jobs "${BUILD_NPROC}"
|
||||
|
||||
- name: Debug failure (Linux)
|
||||
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "IPv4 local port range:"
|
||||
cat /proc/sys/net/ipv4/ip_local_port_range
|
||||
echo "Netstat:"
|
||||
netstat -an
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
run_tests: ${{ !inputs.build_only }}
|
||||
verify_voidstar: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
image: ${{ inputs.image }}
|
||||
config_name: ${{ inputs.config_name }}
|
||||
nproc_subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
154
.github/workflows/reusable-build.yml
vendored
Normal file
154
.github/workflows/reusable-build.yml
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
name: Build rippled
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_dir:
|
||||
description: "The directory where to build."
|
||||
required: true
|
||||
type: string
|
||||
build_type:
|
||||
description: 'The build type to use ("Debug", "Release").'
|
||||
required: true
|
||||
type: string
|
||||
cmake_args:
|
||||
description: "Additional arguments to pass to CMake."
|
||||
required: true
|
||||
type: string
|
||||
cmake_target:
|
||||
description: "The CMake target to build."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
runs_on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
config_name:
|
||||
description: "The name of the configuration."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
nproc_subtract:
|
||||
description: "The number of processors to subtract when calculating parallelism."
|
||||
required: true
|
||||
type: number
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
required: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||
with:
|
||||
disable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
uses: ./.github/actions/build-deps
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
|
||||
- name: Build the binary
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel ${BUILD_NPROC} \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Put built binaries in one location
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE_DIR: ${{ runner.os == 'Windows' && inputs.build_type || '' }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
mkdir -p ./binaries/doctest/
|
||||
|
||||
cp ./${BUILD_TYPE_DIR}/rippled* ./binaries/
|
||||
if [ "${CMAKE_TARGET}" != 'coverage' ]; then
|
||||
cp ./src/tests/libxrpl/${BUILD_TYPE_DIR}/xrpl.test.* ./binaries/doctest/
|
||||
fi
|
||||
|
||||
- name: Upload rippled artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
path: ${{ env.BUILD_DIR }}/binaries/
|
||||
retention-days: 3
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ github.repository_owner == 'XRPLF' && inputs.cmake_target == 'coverage' }}
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: ${{ inputs.build_dir }}/coverage.xml
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
111
.github/workflows/reusable-test.yml
vendored
Normal file
111
.github/workflows/reusable-test.yml
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
name: Test rippled
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
verify_voidstar:
|
||||
description: "Whether to verify the presence of voidstar instrumentation."
|
||||
required: true
|
||||
type: boolean
|
||||
run_tests:
|
||||
description: "Whether to run unit tests"
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
runs_on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
config_name:
|
||||
description: "The name of the configuration."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
nproc_subtract:
|
||||
description: "The number of processors to subtract when calculating parallelism."
|
||||
required: true
|
||||
type: number
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Download rippled artifact
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
|
||||
- name: Make binary executable (Linux and macOS)
|
||||
shell: bash
|
||||
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
|
||||
run: |
|
||||
chmod +x ./rippled
|
||||
|
||||
- name: Check linking (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
ldd ./rippled
|
||||
if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
|
||||
echo 'The binary is statically linked.'
|
||||
else
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verifying presence of instrumentation
|
||||
if: ${{ inputs.verify_voidstar }}
|
||||
shell: bash
|
||||
run: |
|
||||
./rippled --version | grep libvoidstar
|
||||
|
||||
- name: Run the embedded tests
|
||||
if: ${{ inputs.run_tests }}
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
./rippled --unittest --unittest-jobs ${BUILD_NPROC}
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ inputs.run_tests }}
|
||||
env:
|
||||
EXT: ${{ runner.os == 'Windows' && '.exe' || '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
for test_file in ./doctest/*${EXT}; do
|
||||
echo "Executing $test_file"
|
||||
chmod +x "$test_file"
|
||||
if [[ "${{ runner.os }}" == "Windows" && "$test_file" == "./doctest/xrpl.test.net.exe" ]]; then
|
||||
echo "Skipping $test_file on Windows"
|
||||
else
|
||||
"$test_file"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Debug failure (Linux)
|
||||
if: ${{ failure() && runner.os == 'Linux' && inputs.run_tests }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "IPv4 local port range:"
|
||||
cat /proc/sys/net/ipv4/ip_local_port_range
|
||||
echo "Netstat:"
|
||||
netstat -an
|
||||
@@ -22,4 +22,20 @@ function(xrpl_add_test name)
|
||||
UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
|
||||
|
||||
add_test(NAME ${target} COMMAND ${target})
|
||||
set_tests_properties(
|
||||
${target} PROPERTIES
|
||||
FIXTURES_REQUIRED ${target}_fixture
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME ${target}.build
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build ${CMAKE_BINARY_DIR}
|
||||
--config $<CONFIG>
|
||||
--target ${target}
|
||||
)
|
||||
set_tests_properties(${target}.build PROPERTIES
|
||||
FIXTURES_SETUP ${target}_fixture
|
||||
)
|
||||
endfunction()
|
||||
|
||||
@@ -37,6 +37,8 @@ install(
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(CODE "set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")")
|
||||
|
||||
install (EXPORT XrplExports
|
||||
FILE XrplTargets.cmake
|
||||
NAMESPACE Xrpl::
|
||||
@@ -67,7 +69,7 @@ if (is_root_project AND TARGET xrpld)
|
||||
install(CODE "
|
||||
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
|
||||
include(create_symbolic_link)
|
||||
create_symbolic_link(rippled${suffix} \
|
||||
create_symbolic_link(xrpld${suffix} \
|
||||
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/xrpld${suffix})
|
||||
")
|
||||
endif ()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -139,9 +140,9 @@ public:
|
||||
using ArrayIndex = UInt;
|
||||
|
||||
static Value const null;
|
||||
static Int const minInt;
|
||||
static Int const maxInt;
|
||||
static UInt const maxUInt;
|
||||
static constexpr Int minInt = std::numeric_limits<Int>::min();
|
||||
static constexpr Int maxInt = std::numeric_limits<Int>::max();
|
||||
static constexpr UInt maxUInt = std::numeric_limits<UInt>::max();
|
||||
|
||||
private:
|
||||
class CZString
|
||||
@@ -244,6 +245,10 @@ public:
|
||||
bool
|
||||
asBool() const;
|
||||
|
||||
/** Correct absolute value from int or unsigned int */
|
||||
UInt
|
||||
asAbsUInt() const;
|
||||
|
||||
// TODO: What is the "empty()" method this docstring mentions?
|
||||
/** isNull() tests to see if this field is null. Don't use this method to
|
||||
test for emptiness: use empty(). */
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
namespace Json {
|
||||
|
||||
Value const Value::null;
|
||||
Int const Value::minInt = Int(~(UInt(-1) / 2));
|
||||
Int const Value::maxInt = Int(UInt(-1) / 2);
|
||||
UInt const Value::maxUInt = UInt(-1);
|
||||
|
||||
class DefaultValueAllocator : public ValueAllocator
|
||||
{
|
||||
@@ -550,6 +547,69 @@ Value::asInt() const
|
||||
return 0; // unreachable;
|
||||
}
|
||||
|
||||
UInt
|
||||
Value::asAbsUInt() const
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case nullValue:
|
||||
return 0;
|
||||
|
||||
case intValue: {
|
||||
// Doing this conversion through int64 avoids overflow error for
|
||||
// value_.int_ = -1 * 2^31 i.e. numeric_limits<int>::min().
|
||||
if (value_.int_ < 0)
|
||||
return static_cast<std::int64_t>(value_.int_) * -1;
|
||||
return value_.int_;
|
||||
}
|
||||
|
||||
case uintValue:
|
||||
return value_.uint_;
|
||||
|
||||
case realValue: {
|
||||
if (value_.real_ < 0)
|
||||
{
|
||||
JSON_ASSERT_MESSAGE(
|
||||
-1 * value_.real_ <= maxUInt,
|
||||
"Real out of unsigned integer range");
|
||||
return UInt(-1 * value_.real_);
|
||||
}
|
||||
JSON_ASSERT_MESSAGE(
|
||||
value_.real_ <= maxUInt, "Real out of unsigned integer range");
|
||||
return UInt(value_.real_);
|
||||
}
|
||||
|
||||
case booleanValue:
|
||||
return value_.bool_ ? 1 : 0;
|
||||
|
||||
case stringValue: {
|
||||
char const* const str{value_.string_ ? value_.string_ : ""};
|
||||
auto const temp = beast::lexicalCastThrow<std::int64_t>(str);
|
||||
if (temp < 0)
|
||||
{
|
||||
JSON_ASSERT_MESSAGE(
|
||||
-1 * temp <= maxUInt,
|
||||
"String out of unsigned integer range");
|
||||
return -1 * temp;
|
||||
}
|
||||
JSON_ASSERT_MESSAGE(
|
||||
temp <= maxUInt, "String out of unsigned integer range");
|
||||
return temp;
|
||||
}
|
||||
|
||||
case arrayValue:
|
||||
case objectValue:
|
||||
JSON_ASSERT_MESSAGE(false, "Type is not convertible to int");
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asAbsInt : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable;
|
||||
}
|
||||
|
||||
Value::UInt
|
||||
Value::asUInt() const
|
||||
{
|
||||
|
||||
@@ -1087,7 +1087,7 @@ amountFromJson(SField const& name, Json::Value const& v)
|
||||
}
|
||||
else
|
||||
{
|
||||
parts.mantissa = -value.asInt();
|
||||
parts.mantissa = value.asAbsUInt();
|
||||
parts.negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ numberFromJson(SField const& field, Json::Value const& value)
|
||||
}
|
||||
else
|
||||
{
|
||||
parts.mantissa = -value.asInt();
|
||||
parts.mantissa = value.asAbsUInt();
|
||||
parts.negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ public:
|
||||
false,
|
||||
true,
|
||||
1,
|
||||
std::chrono::seconds{Json::Value::maxInt + 1}}});
|
||||
std::chrono::seconds{Json::Value::minInt}}});
|
||||
// force an out-of-range validUntil value on the future list
|
||||
// The first list is accepted. The second fails. The parser
|
||||
// returns the "best" result, so this looks like a success.
|
||||
@@ -608,7 +608,7 @@ public:
|
||||
false,
|
||||
true,
|
||||
1,
|
||||
std::chrono::seconds{Json::Value::maxInt + 1},
|
||||
std::chrono::seconds{Json::Value::minInt},
|
||||
std::chrono::seconds{Json::Value::maxInt - 6000}}});
|
||||
// verify refresh intervals are properly clamped
|
||||
testFetchList(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/basics/random.h>
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -585,6 +586,216 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
testParseJson()
|
||||
{
|
||||
static_assert(!std::is_convertible_v<STAmount*, Number*>);
|
||||
|
||||
{
|
||||
STAmount const stnum{sfNumber};
|
||||
BEAST_EXPECT(stnum.getSType() == STI_AMOUNT);
|
||||
BEAST_EXPECT(stnum.getText() == "0");
|
||||
BEAST_EXPECT(stnum.isDefault() == true);
|
||||
BEAST_EXPECT(stnum.value() == Number{0});
|
||||
}
|
||||
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, Json::Value(42)) == XRPAmount(42));
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, Json::Value(-42)) == XRPAmount(-42));
|
||||
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, Json::UInt(42)) == XRPAmount(42));
|
||||
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "-123") == XRPAmount(-123));
|
||||
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "123") == XRPAmount(123));
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "-123") == XRPAmount(-123));
|
||||
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "3.14e2") == XRPAmount(314));
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, "-3.14e2") == XRPAmount(-314));
|
||||
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "0") == XRPAmount(0));
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, "-0") == XRPAmount(0));
|
||||
|
||||
constexpr auto imin = std::numeric_limits<int>::min();
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, imin) == XRPAmount(imin));
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, std::to_string(imin)) ==
|
||||
XRPAmount(imin));
|
||||
|
||||
constexpr auto imax = std::numeric_limits<int>::max();
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, imax) == XRPAmount(imax));
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, std::to_string(imax)) ==
|
||||
XRPAmount(imax));
|
||||
|
||||
constexpr auto umax = std::numeric_limits<unsigned int>::max();
|
||||
BEAST_EXPECT(amountFromJson(sfNumber, umax) == XRPAmount(umax));
|
||||
BEAST_EXPECT(
|
||||
amountFromJson(sfNumber, std::to_string(umax)) ==
|
||||
XRPAmount(umax));
|
||||
|
||||
// XRP does not handle fractional part
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "0.0");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected =
|
||||
"XRP and MPT must be specified as integral amount.";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
// XRP does not handle fractional part
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "1000e-2");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected =
|
||||
"XRP and MPT must be specified as integral amount.";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
// Obvious non-numbers tested here
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "e");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'e' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "1e");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'1e' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "e2");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'e2' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, Json::Value());
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected =
|
||||
"XRP may not be specified with a null Json value";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(
|
||||
sfNumber,
|
||||
"123456789012345678901234567890123456789012345678901234"
|
||||
"5678"
|
||||
"901234567890123456789012345678901234567890123456789012"
|
||||
"3456"
|
||||
"78901234567890123456789012345678901234567890");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::bad_cast const& e)
|
||||
{
|
||||
BEAST_EXPECT(true);
|
||||
}
|
||||
|
||||
// We do not handle leading zeros
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "001");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'001' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "000.0");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'000.0' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
// We do not handle dangling dot
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, ".1");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'.1' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "1.");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'1.' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto _ = amountFromJson(sfNumber, "1.e3");
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::runtime_error const& e)
|
||||
{
|
||||
std::string const expected = "'1.e3' is not a number";
|
||||
BEAST_EXPECT(e.what() == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testConvertXRP()
|
||||
{
|
||||
@@ -1022,6 +1233,7 @@ public:
|
||||
testArithmetic();
|
||||
testUnderflow();
|
||||
testRounding();
|
||||
testParseJson();
|
||||
testConvertXRP();
|
||||
testConvertIOU();
|
||||
testCanAddXRP();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STNumber.h>
|
||||
|
||||
@@ -126,6 +127,30 @@ struct STNumber_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0));
|
||||
|
||||
constexpr auto imin = std::numeric_limits<int>::min();
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, imin) ==
|
||||
STNumber(sfNumber, Number(imin, 0)));
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, std::to_string(imin)) ==
|
||||
STNumber(sfNumber, Number(imin, 0)));
|
||||
|
||||
constexpr auto imax = std::numeric_limits<int>::max();
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, imax) ==
|
||||
STNumber(sfNumber, Number(imax, 0)));
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, std::to_string(imax)) ==
|
||||
STNumber(sfNumber, Number(imax, 0)));
|
||||
|
||||
constexpr auto umax = std::numeric_limits<unsigned int>::max();
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, umax) ==
|
||||
STNumber(sfNumber, Number(umax, 0)));
|
||||
BEAST_EXPECT(
|
||||
numberFromJson(sfNumber, std::to_string(umax)) ==
|
||||
STNumber(sfNumber, Number(umax, 0)));
|
||||
|
||||
// Obvious non-numbers tested here
|
||||
try
|
||||
{
|
||||
|
||||
@@ -14,9 +14,5 @@ xrpl_add_test(crypto)
|
||||
target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(json)
|
||||
target_link_libraries(xrpl.test.json PRIVATE xrpl.imports.test)
|
||||
|
||||
# Network unit tests are currently not supported on Windows
|
||||
if(NOT WIN32)
|
||||
xrpl_add_test(net)
|
||||
target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test)
|
||||
endif()
|
||||
xrpl_add_test(net)
|
||||
target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -15,6 +16,14 @@ namespace ripple {
|
||||
|
||||
TEST_SUITE_BEGIN("json_value");
|
||||
|
||||
TEST_CASE("limits")
|
||||
{
|
||||
using namespace Json;
|
||||
static_assert(Value::minInt == Int(~(UInt(-1) / 2)));
|
||||
static_assert(Value::maxInt == Int(UInt(-1) / 2));
|
||||
static_assert(Value::maxUInt == UInt(-1));
|
||||
}
|
||||
|
||||
TEST_CASE("construct and compare Json::StaticString")
|
||||
{
|
||||
static constexpr char sample[]{"Contents of a Json::StaticString"};
|
||||
@@ -582,8 +591,6 @@ TEST_CASE("bad json")
|
||||
|
||||
TEST_CASE("edge cases")
|
||||
{
|
||||
std::string json;
|
||||
|
||||
std::uint32_t max_uint = std::numeric_limits<std::uint32_t>::max();
|
||||
std::int32_t max_int = std::numeric_limits<std::int32_t>::max();
|
||||
std::int32_t min_int = std::numeric_limits<std::int32_t>::min();
|
||||
@@ -592,71 +599,145 @@ TEST_CASE("edge cases")
|
||||
std::int32_t a_large_int = max_int - 1978;
|
||||
std::int32_t a_small_int = min_int + 1978;
|
||||
|
||||
json = "{\"max_uint\":" + std::to_string(max_uint);
|
||||
json += ",\"max_int\":" + std::to_string(max_int);
|
||||
json += ",\"min_int\":" + std::to_string(min_int);
|
||||
json += ",\"a_uint\":" + std::to_string(a_uint);
|
||||
json += ",\"a_large_int\":" + std::to_string(a_large_int);
|
||||
json += ",\"a_small_int\":" + std::to_string(a_small_int);
|
||||
json += "}";
|
||||
{
|
||||
std::string json = "{\"max_uint\":" + std::to_string(max_uint);
|
||||
json += ",\"max_int\":" + std::to_string(max_int);
|
||||
json += ",\"min_int\":" + std::to_string(min_int);
|
||||
json += ",\"a_uint\":" + std::to_string(a_uint);
|
||||
json += ",\"a_large_int\":" + std::to_string(a_large_int);
|
||||
json += ",\"a_small_int\":" + std::to_string(a_small_int);
|
||||
json += "}";
|
||||
|
||||
Json::Value j1;
|
||||
Json::Reader r1;
|
||||
Json::Value j1;
|
||||
Json::Reader r1;
|
||||
|
||||
CHECK(r1.parse(json, j1));
|
||||
CHECK(j1["max_uint"].asUInt() == max_uint);
|
||||
CHECK(j1["max_int"].asInt() == max_int);
|
||||
CHECK(j1["min_int"].asInt() == min_int);
|
||||
CHECK(j1["a_uint"].asUInt() == a_uint);
|
||||
CHECK(j1["a_uint"] > a_large_int);
|
||||
CHECK(j1["a_uint"] > a_small_int);
|
||||
CHECK(j1["a_large_int"].asInt() == a_large_int);
|
||||
CHECK(j1["a_large_int"].asUInt() == a_large_int);
|
||||
CHECK(j1["a_large_int"] < a_uint);
|
||||
CHECK(j1["a_small_int"].asInt() == a_small_int);
|
||||
CHECK(j1["a_small_int"] < a_uint);
|
||||
CHECK(r1.parse(json, j1));
|
||||
CHECK(j1["max_uint"].asUInt() == max_uint);
|
||||
CHECK(j1["max_uint"].asAbsUInt() == max_uint);
|
||||
CHECK(j1["max_int"].asInt() == max_int);
|
||||
CHECK(j1["max_int"].asAbsUInt() == max_int);
|
||||
CHECK(j1["min_int"].asInt() == min_int);
|
||||
CHECK(
|
||||
j1["min_int"].asAbsUInt() ==
|
||||
static_cast<std::int64_t>(min_int) * -1);
|
||||
CHECK(j1["a_uint"].asUInt() == a_uint);
|
||||
CHECK(j1["a_uint"].asAbsUInt() == a_uint);
|
||||
CHECK(j1["a_uint"] > a_large_int);
|
||||
CHECK(j1["a_uint"] > a_small_int);
|
||||
CHECK(j1["a_large_int"].asInt() == a_large_int);
|
||||
CHECK(j1["a_large_int"].asAbsUInt() == a_large_int);
|
||||
CHECK(j1["a_large_int"].asUInt() == a_large_int);
|
||||
CHECK(j1["a_large_int"] < a_uint);
|
||||
CHECK(j1["a_small_int"].asInt() == a_small_int);
|
||||
CHECK(
|
||||
j1["a_small_int"].asAbsUInt() ==
|
||||
static_cast<std::int64_t>(a_small_int) * -1);
|
||||
CHECK(j1["a_small_int"] < a_uint);
|
||||
}
|
||||
|
||||
json = "{\"overflow\":";
|
||||
json += std::to_string(std::uint64_t(max_uint) + 1);
|
||||
json += "}";
|
||||
std::uint64_t overflow = std::uint64_t(max_uint) + 1;
|
||||
{
|
||||
std::string json = "{\"overflow\":";
|
||||
json += std::to_string(overflow);
|
||||
json += "}";
|
||||
|
||||
Json::Value j2;
|
||||
Json::Reader r2;
|
||||
Json::Value j2;
|
||||
Json::Reader r2;
|
||||
|
||||
CHECK(!r2.parse(json, j2));
|
||||
CHECK(!r2.parse(json, j2));
|
||||
}
|
||||
|
||||
json = "{\"underflow\":";
|
||||
json += std::to_string(std::int64_t(min_int) - 1);
|
||||
json += "}";
|
||||
std::int64_t underflow = std::int64_t(min_int) - 1;
|
||||
{
|
||||
std::string json = "{\"underflow\":";
|
||||
json += std::to_string(underflow);
|
||||
json += "}";
|
||||
|
||||
Json::Value j3;
|
||||
Json::Reader r3;
|
||||
Json::Value j3;
|
||||
Json::Reader r3;
|
||||
|
||||
CHECK(!r3.parse(json, j3));
|
||||
CHECK(!r3.parse(json, j3));
|
||||
}
|
||||
|
||||
Json::Value intString{"4294967296"};
|
||||
CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
|
||||
{
|
||||
Json::Value intString{std::to_string(overflow)};
|
||||
CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
|
||||
CHECK_THROWS_AS(intString.asAbsUInt(), Json::error);
|
||||
|
||||
intString = "4294967295";
|
||||
CHECK(intString.asUInt() == 4294967295u);
|
||||
intString = "4294967295";
|
||||
CHECK(intString.asUInt() == 4294967295u);
|
||||
CHECK(intString.asAbsUInt() == 4294967295u);
|
||||
|
||||
intString = "0";
|
||||
CHECK(intString.asUInt() == 0);
|
||||
intString = "0";
|
||||
CHECK(intString.asUInt() == 0);
|
||||
CHECK(intString.asAbsUInt() == 0);
|
||||
|
||||
intString = "-1";
|
||||
CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
|
||||
intString = "-1";
|
||||
CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
|
||||
CHECK(intString.asAbsUInt() == 1);
|
||||
|
||||
intString = "2147483648";
|
||||
CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
|
||||
intString = "-4294967295";
|
||||
CHECK(intString.asAbsUInt() == 4294967295);
|
||||
|
||||
intString = "2147483647";
|
||||
CHECK(intString.asInt() == 2147483647);
|
||||
intString = "-4294967296";
|
||||
CHECK_THROWS_AS(intString.asAbsUInt(), Json::error);
|
||||
|
||||
intString = "-2147483648";
|
||||
CHECK(intString.asInt() == -2147483648LL); // MSVC wants the LL
|
||||
intString = "2147483648";
|
||||
CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
|
||||
CHECK(intString.asAbsUInt() == 2147483648);
|
||||
|
||||
intString = "-2147483649";
|
||||
CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
|
||||
intString = "2147483647";
|
||||
CHECK(intString.asInt() == 2147483647);
|
||||
CHECK(intString.asAbsUInt() == 2147483647);
|
||||
|
||||
intString = "-2147483648";
|
||||
CHECK(intString.asInt() == -2147483648LL); // MSVC wants the LL
|
||||
CHECK(intString.asAbsUInt() == 2147483648LL);
|
||||
|
||||
intString = "-2147483649";
|
||||
CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
|
||||
CHECK(intString.asAbsUInt() == 2147483649);
|
||||
}
|
||||
|
||||
{
|
||||
Json::Value intReal{4294967297.0};
|
||||
CHECK_THROWS_AS(intReal.asUInt(), Json::error);
|
||||
CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error);
|
||||
|
||||
intReal = 4294967295.0;
|
||||
CHECK(intReal.asUInt() == 4294967295u);
|
||||
CHECK(intReal.asAbsUInt() == 4294967295u);
|
||||
|
||||
intReal = 0.0;
|
||||
CHECK(intReal.asUInt() == 0);
|
||||
CHECK(intReal.asAbsUInt() == 0);
|
||||
|
||||
intReal = -1.0;
|
||||
CHECK_THROWS_AS(intReal.asUInt(), Json::error);
|
||||
CHECK(intReal.asAbsUInt() == 1);
|
||||
|
||||
intReal = -4294967295.0;
|
||||
CHECK(intReal.asAbsUInt() == 4294967295);
|
||||
|
||||
intReal = -4294967296.0;
|
||||
CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error);
|
||||
|
||||
intReal = 2147483648.0;
|
||||
CHECK_THROWS_AS(intReal.asInt(), Json::error);
|
||||
CHECK(intReal.asAbsUInt() == 2147483648);
|
||||
|
||||
intReal = 2147483647.0;
|
||||
CHECK(intReal.asInt() == 2147483647);
|
||||
CHECK(intReal.asAbsUInt() == 2147483647);
|
||||
|
||||
intReal = -2147483648.0;
|
||||
CHECK(intReal.asInt() == -2147483648LL); // MSVC wants the LL
|
||||
CHECK(intReal.asAbsUInt() == 2147483648LL);
|
||||
|
||||
intReal = -2147483649.0;
|
||||
CHECK_THROWS_AS(intReal.asInt(), Json::error);
|
||||
CHECK(intReal.asAbsUInt() == 2147483649);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("copy")
|
||||
@@ -793,6 +874,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "");
|
||||
CHECK(val.asInt() == 0);
|
||||
CHECK(val.asUInt() == 0);
|
||||
CHECK(val.asAbsUInt() == 0);
|
||||
CHECK(val.asDouble() == 0.0);
|
||||
CHECK(val.asBool() == false);
|
||||
|
||||
@@ -813,6 +895,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "-1234");
|
||||
CHECK(val.asInt() == -1234);
|
||||
CHECK_THROWS_AS(val.asUInt(), Json::error);
|
||||
CHECK(val.asAbsUInt() == 1234u);
|
||||
CHECK(val.asDouble() == -1234.0);
|
||||
CHECK(val.asBool() == true);
|
||||
|
||||
@@ -833,6 +916,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "1234");
|
||||
CHECK(val.asInt() == 1234);
|
||||
CHECK(val.asUInt() == 1234u);
|
||||
CHECK(val.asAbsUInt() == 1234u);
|
||||
CHECK(val.asDouble() == 1234.0);
|
||||
CHECK(val.asBool() == true);
|
||||
|
||||
@@ -853,6 +937,7 @@ TEST_CASE("conversions")
|
||||
CHECK(std::regex_match(val.asString(), std::regex("^2\\.0*$")));
|
||||
CHECK(val.asInt() == 2);
|
||||
CHECK(val.asUInt() == 2u);
|
||||
CHECK(val.asAbsUInt() == 2u);
|
||||
CHECK(val.asDouble() == 2.0);
|
||||
CHECK(val.asBool() == true);
|
||||
|
||||
@@ -873,6 +958,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "54321");
|
||||
CHECK(val.asInt() == 54321);
|
||||
CHECK(val.asUInt() == 54321u);
|
||||
CHECK(val.asAbsUInt() == 54321);
|
||||
CHECK_THROWS_AS(val.asDouble(), Json::error);
|
||||
CHECK(val.asBool() == true);
|
||||
|
||||
@@ -893,6 +979,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "");
|
||||
CHECK_THROWS_AS(val.asInt(), std::exception);
|
||||
CHECK_THROWS_AS(val.asUInt(), std::exception);
|
||||
CHECK_THROWS_AS(val.asAbsUInt(), std::exception);
|
||||
CHECK_THROWS_AS(val.asDouble(), std::exception);
|
||||
CHECK(val.asBool() == false);
|
||||
|
||||
@@ -913,6 +1000,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "false");
|
||||
CHECK(val.asInt() == 0);
|
||||
CHECK(val.asUInt() == 0);
|
||||
CHECK(val.asAbsUInt() == 0);
|
||||
CHECK(val.asDouble() == 0.0);
|
||||
CHECK(val.asBool() == false);
|
||||
|
||||
@@ -933,6 +1021,7 @@ TEST_CASE("conversions")
|
||||
CHECK(val.asString() == "true");
|
||||
CHECK(val.asInt() == 1);
|
||||
CHECK(val.asUInt() == 1);
|
||||
CHECK(val.asAbsUInt() == 1);
|
||||
CHECK(val.asDouble() == 1.0);
|
||||
CHECK(val.asBool() == true);
|
||||
|
||||
@@ -953,6 +1042,7 @@ TEST_CASE("conversions")
|
||||
CHECK_THROWS_AS(val.asString(), Json::error);
|
||||
CHECK_THROWS_AS(val.asInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asUInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asAbsUInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asDouble(), Json::error);
|
||||
CHECK(val.asBool() == false); // empty or not
|
||||
|
||||
@@ -973,6 +1063,7 @@ TEST_CASE("conversions")
|
||||
CHECK_THROWS_AS(val.asString(), Json::error);
|
||||
CHECK_THROWS_AS(val.asInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asUInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asAbsUInt(), Json::error);
|
||||
CHECK_THROWS_AS(val.asDouble(), Json::error);
|
||||
CHECK(val.asBool() == false); // empty or not
|
||||
|
||||
|
||||
Reference in New Issue
Block a user