From e18f27f5f7e186e4fb0d6c8ddce34c2db72f80b3 Mon Sep 17 00:00:00 2001 From: Vlad <129996061+vvysokikh1@users.noreply.github.com> Date: Thu, 26 Jun 2025 20:35:31 +0100 Subject: [PATCH] test: switch some unit tests to doctest (#5383) This change moves some tests from the current unit tests that are compiled into the rippled binary to using the doctest framework. --- .github/workflows/macos.yml | 5 +- .github/workflows/nix.yml | 10 +- .github/workflows/windows.yml | 5 +- Builds/levelization/results/ordering.txt | 1 + CMakeLists.txt | 10 + cmake/xrpl_add_test.cmake | 41 +++ conanfile.py | 1 + src/test/basics/RangeSet_test.cpp | 144 ---------- src/test/basics/Slice_test.cpp | 116 -------- src/test/basics/base64_test.cpp | 82 ------ src/test/basics/mulDiv_test.cpp | 62 ----- src/test/basics/scope_test.cpp | 193 ------------- src/test/basics/tagged_integer_test.cpp | 258 ------------------ src/tests/README.md | 4 + src/tests/libxrpl/CMakeLists.txt | 14 + src/tests/libxrpl/basics/RangeSet.cpp | 129 +++++++++ src/tests/libxrpl/basics/Slice.cpp | 105 +++++++ src/tests/libxrpl/basics/base64.cpp | 67 +++++ .../libxrpl/basics/contract.cpp} | 51 ++-- src/tests/libxrpl/basics/main.cpp | 2 + src/tests/libxrpl/basics/mulDiv.cpp | 64 +++++ src/tests/libxrpl/basics/scope.cpp | 174 ++++++++++++ src/tests/libxrpl/basics/tagged_integer.cpp | 247 +++++++++++++++++ .../libxrpl/crypto/csprng.cpp} | 48 +--- src/tests/libxrpl/crypto/main.cpp | 2 + 25 files changed, 908 insertions(+), 927 deletions(-) create mode 100644 cmake/xrpl_add_test.cmake delete mode 100644 src/test/basics/RangeSet_test.cpp delete mode 100644 src/test/basics/Slice_test.cpp delete mode 100644 src/test/basics/base64_test.cpp delete mode 100644 src/test/basics/mulDiv_test.cpp delete mode 100644 src/test/basics/scope_test.cpp delete mode 100644 src/test/basics/tagged_integer_test.cpp create mode 100644 src/tests/README.md create mode 100644 src/tests/libxrpl/CMakeLists.txt create mode 100644 src/tests/libxrpl/basics/RangeSet.cpp create mode 100644 src/tests/libxrpl/basics/Slice.cpp create mode 100644 src/tests/libxrpl/basics/base64.cpp rename src/{test/basics/contract_test.cpp => tests/libxrpl/basics/contract.cpp} (60%) create mode 100644 src/tests/libxrpl/basics/main.cpp create mode 100644 src/tests/libxrpl/basics/mulDiv.cpp create mode 100644 src/tests/libxrpl/basics/scope.cpp create mode 100644 src/tests/libxrpl/basics/tagged_integer.cpp rename src/{test/core/CryptoPRNG_test.cpp => tests/libxrpl/crypto/csprng.cpp} (58%) create mode 100644 src/tests/libxrpl/crypto/main.cpp diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 63d54175ea..e533c6eb41 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -96,4 +96,7 @@ jobs: run: | n=$(nproc) echo "Using $n test jobs" - ${build_dir}/rippled --unittest --unittest-jobs $n + + cd ${build_dir} + ./rippled --unittest --unittest-jobs $n + ctest -j $n --output-on-failure diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index de59e07761..0ba7b0f212 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -163,7 +163,9 @@ jobs: cmake-args: "-Dassert=TRUE -Dwerr=TRUE ${{ matrix.cmake-args }}" - name: test run: | - ${build_dir}/rippled --unittest --unittest-jobs $(nproc) + cd ${build_dir} + ./rippled --unittest --unittest-jobs $(nproc) + ctest -j $(nproc) --output-on-failure reference-fee-test: strategy: @@ -217,8 +219,9 @@ jobs: cmake-args: "-Dassert=TRUE -Dwerr=TRUE ${{ matrix.cmake-args }}" - name: test run: | - ${build_dir}/rippled --unittest --unittest-jobs $(nproc) - + cd ${build_dir} + ./rippled --unittest --unittest-jobs $(nproc) + ctest -j $(nproc) --output-on-failure coverage: strategy: fail-fast: false @@ -441,3 +444,4 @@ jobs: run: | cd ${BUILD_DIR} ./rippled -u --unittest-jobs $(( $(nproc)/4 )) + ctest -j $(nproc) --output-on-failure diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 1d90c2ef58..7c83e7f300 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -95,5 +95,6 @@ jobs: shell: bash if: ${{ matrix.configuration.tests }} run: | - ${build_dir}/${{ matrix.configuration.type }}/rippled --unittest \ - --unittest-jobs $(nproc) + cd ${build_dir}/${{ matrix.configuration.type }} + ./rippled --unittest --unittest-jobs $(nproc) + ctest -j $(nproc) --output-on-failure diff --git a/Builds/levelization/results/ordering.txt b/Builds/levelization/results/ordering.txt index eca7fc6dc2..ce22d8edb0 100644 --- a/Builds/levelization/results/ordering.txt +++ b/Builds/levelization/results/ordering.txt @@ -132,6 +132,7 @@ test.shamap > xrpl.protocol test.toplevel > test.csf test.toplevel > xrpl.json test.unit_test > xrpl.basics +tests.libxrpl > xrpl.basics xrpl.json > xrpl.basics xrpl.protocol > xrpl.basics xrpl.protocol > xrpl.json diff --git a/CMakeLists.txt b/CMakeLists.txt index a9f063db57..c71fb68599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,11 @@ set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2 ) set(SECP256K1_INSTALL TRUE) +set(SECP256K1_BUILD_BENCHMARK FALSE) +set(SECP256K1_BUILD_TESTS FALSE) +set(SECP256K1_BUILD_EXHAUSTIVE_TESTS FALSE) +set(SECP256K1_BUILD_CTIME_TESTS FALSE) +set(SECP256K1_BUILD_EXAMPLES FALSE) add_subdirectory(external/secp256k1) add_library(secp256k1::secp256k1 ALIAS secp256k1) add_subdirectory(external/ed25519-donna) @@ -144,3 +149,8 @@ set(PROJECT_EXPORT_SET RippleExports) include(RippledCore) include(RippledInstall) include(RippledValidatorKeys) + +if(tests) + include(CTest) + add_subdirectory(src/tests/libxrpl) +endif() diff --git a/cmake/xrpl_add_test.cmake b/cmake/xrpl_add_test.cmake new file mode 100644 index 0000000000..d61f4ece3d --- /dev/null +++ b/cmake/xrpl_add_test.cmake @@ -0,0 +1,41 @@ +include(isolate_headers) + +function(xrpl_add_test name) + set(target ${PROJECT_NAME}.test.${name}) + + file(GLOB_RECURSE sources CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp" + ) + add_executable(${target} EXCLUDE_FROM_ALL ${ARGN} ${sources}) + + isolate_headers( + ${target} + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/tests/${name}" + PRIVATE + ) + + # Make sure the test isn't optimized away in unity builds + set_target_properties(${target} PROPERTIES + UNITY_BUILD_MODE GROUP + 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 $ + --target ${target} + ) + set_tests_properties(${target}.build PROPERTIES + FIXTURES_SETUP ${target}_fixture + ) +endfunction() diff --git a/conanfile.py b/conanfile.py index da8a09611d..1a9e88fc0d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -24,6 +24,7 @@ class Xrpl(ConanFile): } requires = [ + 'doctest/2.4.11', 'grpc/1.50.1', 'libarchive/3.7.6', 'nudb/2.0.8', diff --git a/src/test/basics/RangeSet_test.cpp b/src/test/basics/RangeSet_test.cpp deleted file mode 100644 index e0136ab890..0000000000 --- a/src/test/basics/RangeSet_test.cpp +++ /dev/null @@ -1,144 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -namespace ripple { -class RangeSet_test : public beast::unit_test::suite -{ -public: - void - testPrevMissing() - { - testcase("prevMissing"); - - // Set will include: - // [ 0, 5] - // [10,15] - // [20,25] - // etc... - - RangeSet set; - for (std::uint32_t i = 0; i < 10; ++i) - set.insert(range(10 * i, 10 * i + 5)); - - for (std::uint32_t i = 1; i < 100; ++i) - { - std::optional expected; - // no prev missing in domain for i <= 6 - if (i > 6) - { - std::uint32_t const oneBelowRange = (10 * (i / 10)) - 1; - - expected = ((i % 10) > 6) ? (i - 1) : oneBelowRange; - } - BEAST_EXPECT(prevMissing(set, i) == expected); - } - } - - void - testToString() - { - testcase("toString"); - - RangeSet set; - BEAST_EXPECT(to_string(set) == "empty"); - - set.insert(1); - BEAST_EXPECT(to_string(set) == "1"); - - set.insert(range(4u, 6u)); - BEAST_EXPECT(to_string(set) == "1,4-6"); - - set.insert(2); - BEAST_EXPECT(to_string(set) == "1-2,4-6"); - - set.erase(range(4u, 5u)); - BEAST_EXPECT(to_string(set) == "1-2,6"); - } - - void - testFromString() - { - testcase("fromString"); - - RangeSet set; - - BEAST_EXPECT(!from_string(set, "")); - BEAST_EXPECT(boost::icl::length(set) == 0); - - BEAST_EXPECT(!from_string(set, "#")); - BEAST_EXPECT(boost::icl::length(set) == 0); - - BEAST_EXPECT(!from_string(set, ",")); - BEAST_EXPECT(boost::icl::length(set) == 0); - - BEAST_EXPECT(!from_string(set, ",-")); - BEAST_EXPECT(boost::icl::length(set) == 0); - - BEAST_EXPECT(!from_string(set, "1,,2")); - BEAST_EXPECT(boost::icl::length(set) == 0); - - BEAST_EXPECT(from_string(set, "1")); - BEAST_EXPECT(boost::icl::length(set) == 1); - BEAST_EXPECT(boost::icl::first(set) == 1); - - BEAST_EXPECT(from_string(set, "1,1")); - BEAST_EXPECT(boost::icl::length(set) == 1); - BEAST_EXPECT(boost::icl::first(set) == 1); - - BEAST_EXPECT(from_string(set, "1-1")); - BEAST_EXPECT(boost::icl::length(set) == 1); - BEAST_EXPECT(boost::icl::first(set) == 1); - - BEAST_EXPECT(from_string(set, "1,4-6")); - BEAST_EXPECT(boost::icl::length(set) == 4); - BEAST_EXPECT(boost::icl::first(set) == 1); - BEAST_EXPECT(!boost::icl::contains(set, 2)); - BEAST_EXPECT(!boost::icl::contains(set, 3)); - BEAST_EXPECT(boost::icl::contains(set, 4)); - BEAST_EXPECT(boost::icl::contains(set, 5)); - BEAST_EXPECT(boost::icl::last(set) == 6); - - BEAST_EXPECT(from_string(set, "1-2,4-6")); - BEAST_EXPECT(boost::icl::length(set) == 5); - BEAST_EXPECT(boost::icl::first(set) == 1); - BEAST_EXPECT(boost::icl::contains(set, 2)); - BEAST_EXPECT(boost::icl::contains(set, 4)); - BEAST_EXPECT(boost::icl::last(set) == 6); - - BEAST_EXPECT(from_string(set, "1-2,6")); - BEAST_EXPECT(boost::icl::length(set) == 3); - BEAST_EXPECT(boost::icl::first(set) == 1); - BEAST_EXPECT(boost::icl::contains(set, 2)); - BEAST_EXPECT(boost::icl::last(set) == 6); - } - void - run() override - { - testPrevMissing(); - testToString(); - testFromString(); - } -}; - -BEAST_DEFINE_TESTSUITE(RangeSet, ripple_basics, ripple); - -} // namespace ripple diff --git a/src/test/basics/Slice_test.cpp b/src/test/basics/Slice_test.cpp deleted file mode 100644 index 3d474def79..0000000000 --- a/src/test/basics/Slice_test.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github0.com/ripple/rippled - Copyright (c) 2012-2016 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -#include -#include - -namespace ripple { -namespace test { - -struct Slice_test : beast::unit_test::suite -{ - void - run() override - { - std::uint8_t const data[] = { - 0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, - 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, - 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; - - { - testcase("Equality & Inequality"); - - Slice const s0{}; - - BEAST_EXPECT(s0.size() == 0); - BEAST_EXPECT(s0.data() == nullptr); - BEAST_EXPECT(s0 == s0); - - // Test slices of equal and unequal size pointing to same data: - for (std::size_t i = 0; i != sizeof(data); ++i) - { - Slice const s1{data, i}; - - BEAST_EXPECT(s1.size() == i); - BEAST_EXPECT(s1.data() != nullptr); - - if (i == 0) - BEAST_EXPECT(s1 == s0); - else - BEAST_EXPECT(s1 != s0); - - for (std::size_t j = 0; j != sizeof(data); ++j) - { - Slice const s2{data, j}; - - if (i == j) - BEAST_EXPECT(s1 == s2); - else - BEAST_EXPECT(s1 != s2); - } - } - - // Test slices of equal size but pointing to different data: - std::array a; - std::array b; - - for (std::size_t i = 0; i != sizeof(data); ++i) - a[i] = b[i] = data[i]; - - BEAST_EXPECT(makeSlice(a) == makeSlice(b)); - b[7]++; - BEAST_EXPECT(makeSlice(a) != makeSlice(b)); - a[7]++; - BEAST_EXPECT(makeSlice(a) == makeSlice(b)); - } - - { - testcase("Indexing"); - - Slice const s{data, sizeof(data)}; - - for (std::size_t i = 0; i != sizeof(data); ++i) - BEAST_EXPECT(s[i] == data[i]); - } - - { - testcase("Advancing"); - - for (std::size_t i = 0; i < sizeof(data); ++i) - { - for (std::size_t j = 0; i + j < sizeof(data); ++j) - { - Slice s(data + i, sizeof(data) - i); - s += j; - - BEAST_EXPECT(s.data() == data + i + j); - BEAST_EXPECT(s.size() == sizeof(data) - i - j); - } - } - } - } -}; - -BEAST_DEFINE_TESTSUITE(Slice, ripple_basics, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/basics/base64_test.cpp b/src/test/basics/base64_test.cpp deleted file mode 100644 index b6d67c7c06..0000000000 --- a/src/test/basics/base64_test.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012-2018 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -// -// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#include -#include - -namespace ripple { - -class base64_test : public beast::unit_test::suite -{ -public: - void - check(std::string const& in, std::string const& out) - { - auto const encoded = base64_encode(in); - BEAST_EXPECT(encoded == out); - BEAST_EXPECT(base64_decode(encoded) == in); - } - - void - run() override - { - check("", ""); - check("f", "Zg=="); - check("fo", "Zm8="); - check("foo", "Zm9v"); - check("foob", "Zm9vYg=="); - check("fooba", "Zm9vYmE="); - check("foobar", "Zm9vYmFy"); - - check( - "Man is distinguished, not only by his reason, but by this " - "singular passion from " - "other animals, which is a lust of the mind, that by a " - "perseverance of delight " - "in the continued and indefatigable generation of knowledge, " - "exceeds the short " - "vehemence of any carnal pleasure.", - "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dC" - "BieSB0aGlz" - "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" - "x1c3Qgb2Yg" - "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aG" - "UgY29udGlu" - "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleG" - "NlZWRzIHRo" - "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="); - - std::string const notBase64 = "not_base64!!"; - std::string const truncated = "not"; - BEAST_EXPECT(base64_decode(notBase64) == base64_decode(truncated)); - } -}; - -BEAST_DEFINE_TESTSUITE(base64, ripple_basics, ripple); - -} // namespace ripple diff --git a/src/test/basics/mulDiv_test.cpp b/src/test/basics/mulDiv_test.cpp deleted file mode 100644 index 61521577d9..0000000000 --- a/src/test/basics/mulDiv_test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012-2016 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -namespace ripple { -namespace test { - -struct mulDiv_test : beast::unit_test::suite -{ - void - run() override - { - auto const max = std::numeric_limits::max(); - std::uint64_t const max32 = std::numeric_limits::max(); - - auto result = mulDiv(85, 20, 5); - BEAST_EXPECT(result && *result == 340); - result = mulDiv(20, 85, 5); - BEAST_EXPECT(result && *result == 340); - - result = mulDiv(0, max - 1, max - 3); - BEAST_EXPECT(result && *result == 0); - result = mulDiv(max - 1, 0, max - 3); - BEAST_EXPECT(result && *result == 0); - - result = mulDiv(max, 2, max / 2); - BEAST_EXPECT(result && *result == 4); - result = mulDiv(max, 1000, max / 1000); - BEAST_EXPECT(result && *result == 1000000); - result = mulDiv(max, 1000, max / 1001); - BEAST_EXPECT(result && *result == 1001000); - result = mulDiv(max32 + 1, max32 + 1, 5); - BEAST_EXPECT(result && *result == 3689348814741910323); - - // Overflow - result = mulDiv(max - 1, max - 2, 5); - BEAST_EXPECT(!result); - } -}; - -BEAST_DEFINE_TESTSUITE(mulDiv, ripple_basics, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/basics/scope_test.cpp b/src/test/basics/scope_test.cpp deleted file mode 100644 index 654f7e0a11..0000000000 --- a/src/test/basics/scope_test.cpp +++ /dev/null @@ -1,193 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github0.com/ripple/rippled - Copyright (c) 2021 Ripple Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -namespace ripple { -namespace test { - -struct scope_test : beast::unit_test::suite -{ - void - test_scope_exit() - { - // scope_exit always executes the functor on destruction, - // unless release() is called - int i = 0; - { - scope_exit x{[&i]() { i = 1; }}; - } - BEAST_EXPECT(i == 1); - { - scope_exit x{[&i]() { i = 2; }}; - x.release(); - } - BEAST_EXPECT(i == 1); - { - scope_exit x{[&i]() { i += 2; }}; - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 3); - { - scope_exit x{[&i]() { i = 4; }}; - x.release(); - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 3); - { - try - { - scope_exit x{[&i]() { i = 5; }}; - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 5); - { - try - { - scope_exit x{[&i]() { i = 6; }}; - x.release(); - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 5); - } - - void - test_scope_fail() - { - // scope_fail executes the functor on destruction only - // if an exception is unwinding, unless release() is called - int i = 0; - { - scope_fail x{[&i]() { i = 1; }}; - } - BEAST_EXPECT(i == 0); - { - scope_fail x{[&i]() { i = 2; }}; - x.release(); - } - BEAST_EXPECT(i == 0); - { - scope_fail x{[&i]() { i = 3; }}; - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 0); - { - scope_fail x{[&i]() { i = 4; }}; - x.release(); - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 0); - { - try - { - scope_fail x{[&i]() { i = 5; }}; - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 5); - { - try - { - scope_fail x{[&i]() { i = 6; }}; - x.release(); - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 5); - } - - void - test_scope_success() - { - // scope_success executes the functor on destruction only - // if an exception is not unwinding, unless release() is called - int i = 0; - { - scope_success x{[&i]() { i = 1; }}; - } - BEAST_EXPECT(i == 1); - { - scope_success x{[&i]() { i = 2; }}; - x.release(); - } - BEAST_EXPECT(i == 1); - { - scope_success x{[&i]() { i += 2; }}; - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 3); - { - scope_success x{[&i]() { i = 4; }}; - x.release(); - auto x2 = std::move(x); - } - BEAST_EXPECT(i == 3); - { - try - { - scope_success x{[&i]() { i = 5; }}; - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 3); - { - try - { - scope_success x{[&i]() { i = 6; }}; - x.release(); - throw 1; - } - catch (...) - { - } - } - BEAST_EXPECT(i == 3); - } - - void - run() override - { - test_scope_exit(); - test_scope_fail(); - test_scope_success(); - } -}; - -BEAST_DEFINE_TESTSUITE(scope, ripple_basics, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/basics/tagged_integer_test.cpp b/src/test/basics/tagged_integer_test.cpp deleted file mode 100644 index cb15d246a6..0000000000 --- a/src/test/basics/tagged_integer_test.cpp +++ /dev/null @@ -1,258 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright 2014, Nikolaos D. Bougalis - - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -#include - -namespace ripple { -namespace test { - -class tagged_integer_test : public beast::unit_test::suite -{ -private: - struct Tag1 - { - }; - struct Tag2 - { - }; - - // Static checks that types are not interoperable - - using TagUInt1 = tagged_integer; - using TagUInt2 = tagged_integer; - using TagUInt3 = tagged_integer; - - // Check construction of tagged_integers - static_assert( - std::is_constructible::value, - "TagUInt1 should be constructible using a std::uint32_t"); - - static_assert( - !std::is_constructible::value, - "TagUInt1 should not be constructible using a std::uint64_t"); - - static_assert( - std::is_constructible::value, - "TagUInt3 should be constructible using a std::uint32_t"); - - static_assert( - std::is_constructible::value, - "TagUInt3 should be constructible using a std::uint64_t"); - - // Check assignment of tagged_integers - static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a std::uint32_t"); - - static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a std::uint64_t"); - - static_assert( - !std::is_assignable::value, - "TagUInt3 should not be assignable with a std::uint32_t"); - - static_assert( - !std::is_assignable::value, - "TagUInt3 should not be assignable with a std::uint64_t"); - - static_assert( - std::is_assignable::value, - "TagUInt1 should be assignable with a TagUInt1"); - - static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a TagUInt2"); - - static_assert( - std::is_assignable::value, - "TagUInt3 should be assignable with a TagUInt1"); - - static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a TagUInt3"); - - static_assert( - !std::is_assignable::value, - "TagUInt3 should not be assignable with a TagUInt1"); - - // Check convertibility of tagged_integers - static_assert( - !std::is_convertible::value, - "std::uint32_t should not be convertible to a TagUInt1"); - - static_assert( - !std::is_convertible::value, - "std::uint32_t should not be convertible to a TagUInt3"); - - static_assert( - !std::is_convertible::value, - "std::uint64_t should not be convertible to a TagUInt3"); - - static_assert( - !std::is_convertible::value, - "std::uint64_t should not be convertible to a TagUInt2"); - - static_assert( - !std::is_convertible::value, - "TagUInt1 should not be convertible to TagUInt2"); - - static_assert( - !std::is_convertible::value, - "TagUInt1 should not be convertible to TagUInt3"); - - static_assert( - !std::is_convertible::value, - "TagUInt2 should not be convertible to a TagUInt3"); - -public: - void - run() override - { - using TagInt = tagged_integer; - - { - testcase("Comparison Operators"); - - TagInt const zero(0); - TagInt const one(1); - - BEAST_EXPECT(one == one); - BEAST_EXPECT(!(one == zero)); - - BEAST_EXPECT(one != zero); - BEAST_EXPECT(!(one != one)); - - BEAST_EXPECT(zero < one); - BEAST_EXPECT(!(one < zero)); - - BEAST_EXPECT(one > zero); - BEAST_EXPECT(!(zero > one)); - - BEAST_EXPECT(one >= one); - BEAST_EXPECT(one >= zero); - BEAST_EXPECT(!(zero >= one)); - - BEAST_EXPECT(zero <= one); - BEAST_EXPECT(zero <= zero); - BEAST_EXPECT(!(one <= zero)); - } - - { - testcase("Increment/Decrement Operators"); - TagInt const zero(0); - TagInt const one(1); - TagInt a{0}; - ++a; - BEAST_EXPECT(a == one); - --a; - BEAST_EXPECT(a == zero); - a++; - BEAST_EXPECT(a == one); - a--; - BEAST_EXPECT(a == zero); - } - - { - testcase("Arithmetic Operators"); - TagInt a{-2}; - BEAST_EXPECT(+a == TagInt{-2}); - BEAST_EXPECT(-a == TagInt{2}); - BEAST_EXPECT(TagInt{-3} + TagInt{4} == TagInt{1}); - BEAST_EXPECT(TagInt{-3} - TagInt{4} == TagInt{-7}); - BEAST_EXPECT(TagInt{-3} * TagInt{4} == TagInt{-12}); - BEAST_EXPECT(TagInt{8} / TagInt{4} == TagInt{2}); - BEAST_EXPECT(TagInt{7} % TagInt{4} == TagInt{3}); - - BEAST_EXPECT(~TagInt{8} == TagInt{~TagInt::value_type{8}}); - BEAST_EXPECT((TagInt{6} & TagInt{3}) == TagInt{2}); - BEAST_EXPECT((TagInt{6} | TagInt{3}) == TagInt{7}); - BEAST_EXPECT((TagInt{6} ^ TagInt{3}) == TagInt{5}); - - BEAST_EXPECT((TagInt{4} << TagInt{2}) == TagInt{16}); - BEAST_EXPECT((TagInt{16} >> TagInt{2}) == TagInt{4}); - } - { - testcase("Assignment Operators"); - TagInt a{-2}; - TagInt b{0}; - b = a; - BEAST_EXPECT(b == TagInt{-2}); - - // -3 + 4 == 1 - a = TagInt{-3}; - a += TagInt{4}; - BEAST_EXPECT(a == TagInt{1}); - - // -3 - 4 == -7 - a = TagInt{-3}; - a -= TagInt{4}; - BEAST_EXPECT(a == TagInt{-7}); - - // -3 * 4 == -12 - a = TagInt{-3}; - a *= TagInt{4}; - BEAST_EXPECT(a == TagInt{-12}); - - // 8/4 == 2 - a = TagInt{8}; - a /= TagInt{4}; - BEAST_EXPECT(a == TagInt{2}); - - // 7 % 4 == 3 - a = TagInt{7}; - a %= TagInt{4}; - BEAST_EXPECT(a == TagInt{3}); - - // 6 & 3 == 2 - a = TagInt{6}; - a /= TagInt{3}; - BEAST_EXPECT(a == TagInt{2}); - - // 6 | 3 == 7 - a = TagInt{6}; - a |= TagInt{3}; - BEAST_EXPECT(a == TagInt{7}); - - // 6 ^ 3 == 5 - a = TagInt{6}; - a ^= TagInt{3}; - BEAST_EXPECT(a == TagInt{5}); - - // 4 << 2 == 16 - a = TagInt{4}; - a <<= TagInt{2}; - BEAST_EXPECT(a == TagInt{16}); - - // 16 >> 2 == 4 - a = TagInt{16}; - a >>= TagInt{2}; - BEAST_EXPECT(a == TagInt{4}); - } - } -}; - -BEAST_DEFINE_TESTSUITE(tagged_integer, ripple_basics, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/tests/README.md b/src/tests/README.md new file mode 100644 index 0000000000..8065316580 --- /dev/null +++ b/src/tests/README.md @@ -0,0 +1,4 @@ +# Unit tests +This directory contains unit tests for the project. The difference from existing `src/test` folder +is that we switch to 3rd party testing framework (doctest). We intend to gradually move existing tests +from our own framework to doctest and such tests will be moved to this new folder. diff --git a/src/tests/libxrpl/CMakeLists.txt b/src/tests/libxrpl/CMakeLists.txt new file mode 100644 index 0000000000..68c6fa6cb3 --- /dev/null +++ b/src/tests/libxrpl/CMakeLists.txt @@ -0,0 +1,14 @@ +include(xrpl_add_test) + +# Test requirements. +find_package(doctest REQUIRED) + +# Common library dependencies for the rest of the tests. +add_library(xrpl.imports.test INTERFACE) +target_link_libraries(xrpl.imports.test INTERFACE doctest::doctest xrpl.libxrpl) + +# One test for each module. +xrpl_add_test(basics) +target_link_libraries(xrpl.test.basics PRIVATE xrpl.imports.test) +xrpl_add_test(crypto) +target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test) diff --git a/src/tests/libxrpl/basics/RangeSet.cpp b/src/tests/libxrpl/basics/RangeSet.cpp new file mode 100644 index 0000000000..ac0e1d9551 --- /dev/null +++ b/src/tests/libxrpl/basics/RangeSet.cpp @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +#include +#include + +using namespace ripple; + +TEST_SUITE_BEGIN("RangeSet"); + +TEST_CASE("prevMissing") +{ + // Set will include: + // [ 0, 5] + // [10,15] + // [20,25] + // etc... + + RangeSet set; + for (std::uint32_t i = 0; i < 10; ++i) + set.insert(range(10 * i, 10 * i + 5)); + + for (std::uint32_t i = 1; i < 100; ++i) + { + std::optional expected; + // no prev missing in domain for i <= 6 + if (i > 6) + { + std::uint32_t const oneBelowRange = (10 * (i / 10)) - 1; + + expected = ((i % 10) > 6) ? (i - 1) : oneBelowRange; + } + CHECK(prevMissing(set, i) == expected); + } +} + +TEST_CASE("toString") +{ + RangeSet set; + CHECK(to_string(set) == "empty"); + + set.insert(1); + CHECK(to_string(set) == "1"); + + set.insert(range(4u, 6u)); + CHECK(to_string(set) == "1,4-6"); + + set.insert(2); + CHECK(to_string(set) == "1-2,4-6"); + + set.erase(range(4u, 5u)); + CHECK(to_string(set) == "1-2,6"); +} + +TEST_CASE("fromString") +{ + RangeSet set; + + CHECK(!from_string(set, "")); + CHECK(boost::icl::length(set) == 0); + + CHECK(!from_string(set, "#")); + CHECK(boost::icl::length(set) == 0); + + CHECK(!from_string(set, ",")); + CHECK(boost::icl::length(set) == 0); + + CHECK(!from_string(set, ",-")); + CHECK(boost::icl::length(set) == 0); + + CHECK(!from_string(set, "1,,2")); + CHECK(boost::icl::length(set) == 0); + + CHECK(from_string(set, "1")); + CHECK(boost::icl::length(set) == 1); + CHECK(boost::icl::first(set) == 1); + + CHECK(from_string(set, "1,1")); + CHECK(boost::icl::length(set) == 1); + CHECK(boost::icl::first(set) == 1); + + CHECK(from_string(set, "1-1")); + CHECK(boost::icl::length(set) == 1); + CHECK(boost::icl::first(set) == 1); + + CHECK(from_string(set, "1,4-6")); + CHECK(boost::icl::length(set) == 4); + CHECK(boost::icl::first(set) == 1); + CHECK(!boost::icl::contains(set, 2)); + CHECK(!boost::icl::contains(set, 3)); + CHECK(boost::icl::contains(set, 4)); + CHECK(boost::icl::contains(set, 5)); + CHECK(boost::icl::last(set) == 6); + + CHECK(from_string(set, "1-2,4-6")); + CHECK(boost::icl::length(set) == 5); + CHECK(boost::icl::first(set) == 1); + CHECK(boost::icl::contains(set, 2)); + CHECK(boost::icl::contains(set, 4)); + CHECK(boost::icl::last(set) == 6); + + CHECK(from_string(set, "1-2,6")); + CHECK(boost::icl::length(set) == 3); + CHECK(boost::icl::first(set) == 1); + CHECK(boost::icl::contains(set, 2)); + CHECK(boost::icl::last(set) == 6); +} + +TEST_SUITE_END(); diff --git a/src/tests/libxrpl/basics/Slice.cpp b/src/tests/libxrpl/basics/Slice.cpp new file mode 100644 index 0000000000..eabd9b7dc7 --- /dev/null +++ b/src/tests/libxrpl/basics/Slice.cpp @@ -0,0 +1,105 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +#include +#include + +using namespace ripple; + +static std::uint8_t const data[] = { + 0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, + 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, + 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; + +TEST_SUITE_BEGIN("Slice"); + +TEST_CASE("equality & inequality") +{ + Slice const s0{}; + + CHECK(s0.size() == 0); + CHECK(s0.data() == nullptr); + CHECK(s0 == s0); + + // Test slices of equal and unequal size pointing to same data: + for (std::size_t i = 0; i != sizeof(data); ++i) + { + Slice const s1{data, i}; + + CHECK(s1.size() == i); + CHECK(s1.data() != nullptr); + + if (i == 0) + CHECK(s1 == s0); + else + CHECK(s1 != s0); + + for (std::size_t j = 0; j != sizeof(data); ++j) + { + Slice const s2{data, j}; + + if (i == j) + CHECK(s1 == s2); + else + CHECK(s1 != s2); + } + } + + // Test slices of equal size but pointing to different data: + std::array a; + std::array b; + + for (std::size_t i = 0; i != sizeof(data); ++i) + a[i] = b[i] = data[i]; + + CHECK(makeSlice(a) == makeSlice(b)); + b[7]++; + CHECK(makeSlice(a) != makeSlice(b)); + a[7]++; + CHECK(makeSlice(a) == makeSlice(b)); +} + +TEST_CASE("indexing") +{ + Slice const s{data, sizeof(data)}; + + for (std::size_t i = 0; i != sizeof(data); ++i) + CHECK(s[i] == data[i]); +} + +TEST_CASE("advancing") +{ + for (std::size_t i = 0; i < sizeof(data); ++i) + { + for (std::size_t j = 0; i + j < sizeof(data); ++j) + { + Slice s(data + i, sizeof(data) - i); + s += j; + + CHECK(s.data() == data + i + j); + CHECK(s.size() == sizeof(data) - i - j); + } + } +} + +TEST_SUITE_END(); diff --git a/src/tests/libxrpl/basics/base64.cpp b/src/tests/libxrpl/basics/base64.cpp new file mode 100644 index 0000000000..fe9b86abb1 --- /dev/null +++ b/src/tests/libxrpl/basics/base64.cpp @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +#include + +using namespace ripple; + +static void +check(std::string const& in, std::string const& out) +{ + auto const encoded = base64_encode(in); + CHECK(encoded == out); + CHECK(base64_decode(encoded) == in); +} + +TEST_CASE("base64") +{ + check("", ""); + check("f", "Zg=="); + check("fo", "Zm8="); + check("foo", "Zm9v"); + check("foob", "Zm9vYg=="); + check("fooba", "Zm9vYmE="); + check("foobar", "Zm9vYmFy"); + + check( + "Man is distinguished, not only by his reason, but by this " + "singular passion from " + "other animals, which is a lust of the mind, that by a " + "perseverance of delight " + "in the continued and indefatigable generation of knowledge, " + "exceeds the short " + "vehemence of any carnal pleasure.", + "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dC" + "BieSB0aGlz" + "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" + "x1c3Qgb2Yg" + "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aG" + "UgY29udGlu" + "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleG" + "NlZWRzIHRo" + "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="); + + std::string const notBase64 = "not_base64!!"; + std::string const truncated = "not"; + CHECK(base64_decode(notBase64) == base64_decode(truncated)); +} diff --git a/src/test/basics/contract_test.cpp b/src/tests/libxrpl/basics/contract.cpp similarity index 60% rename from src/test/basics/contract_test.cpp rename to src/tests/libxrpl/basics/contract.cpp index 9595dbabcc..9ddf044f17 100644 --- a/src/test/basics/contract_test.cpp +++ b/src/tests/libxrpl/basics/contract.cpp @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. + Copyright (c) 2012 Ripple Labs Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -18,46 +18,39 @@ //============================================================================== #include -#include +#include + +#include #include -namespace ripple { +using namespace ripple; -class contract_test : public beast::unit_test::suite +TEST_CASE("contract") { -public: - void - run() override + try { + Throw("Throw test"); + } + catch (std::runtime_error const& e1) + { + CHECK(std::string(e1.what()) == "Throw test"); + try { - Throw("Throw test"); + Rethrow(); } - catch (std::runtime_error const& e1) + catch (std::runtime_error const& e2) { - BEAST_EXPECT(std::string(e1.what()) == "Throw test"); - - try - { - Rethrow(); - } - catch (std::runtime_error const& e2) - { - BEAST_EXPECT(std::string(e2.what()) == "Throw test"); - } - catch (...) - { - BEAST_EXPECT(false); - } + CHECK(std::string(e2.what()) == "Throw test"); } catch (...) { - BEAST_EXPECT(false); + CHECK(false); } } -}; - -BEAST_DEFINE_TESTSUITE(contract, basics, ripple); - -} // namespace ripple + catch (...) + { + CHECK(false); + } +} diff --git a/src/tests/libxrpl/basics/main.cpp b/src/tests/libxrpl/basics/main.cpp new file mode 100644 index 0000000000..0a3f254ea8 --- /dev/null +++ b/src/tests/libxrpl/basics/main.cpp @@ -0,0 +1,2 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include diff --git a/src/tests/libxrpl/basics/mulDiv.cpp b/src/tests/libxrpl/basics/mulDiv.cpp new file mode 100644 index 0000000000..bdbbfdc741 --- /dev/null +++ b/src/tests/libxrpl/basics/mulDiv.cpp @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +#include +#include + +using namespace ripple; + +TEST_CASE("mulDiv") +{ + auto const max = std::numeric_limits::max(); + std::uint64_t const max32 = std::numeric_limits::max(); + + auto result = mulDiv(85, 20, 5); + REQUIRE(result); + CHECK(*result == 340); + result = mulDiv(20, 85, 5); + REQUIRE(result); + CHECK(*result == 340); + + result = mulDiv(0, max - 1, max - 3); + REQUIRE(result); + CHECK(*result == 0); + result = mulDiv(max - 1, 0, max - 3); + REQUIRE(result); + CHECK(*result == 0); + + result = mulDiv(max, 2, max / 2); + REQUIRE(result); + CHECK(*result == 4); + result = mulDiv(max, 1000, max / 1000); + REQUIRE(result); + CHECK(*result == 1000000); + result = mulDiv(max, 1000, max / 1001); + REQUIRE(result); + CHECK(*result == 1001000); + result = mulDiv(max32 + 1, max32 + 1, 5); + REQUIRE(result); + CHECK(*result == 3689348814741910323); + + // Overflow + result = mulDiv(max - 1, max - 2, 5); + CHECK(!result); +} diff --git a/src/tests/libxrpl/basics/scope.cpp b/src/tests/libxrpl/basics/scope.cpp new file mode 100644 index 0000000000..c9cfc1e7f8 --- /dev/null +++ b/src/tests/libxrpl/basics/scope.cpp @@ -0,0 +1,174 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2021 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +using namespace ripple; + +TEST_CASE("scope_exit") +{ + // scope_exit always executes the functor on destruction, + // unless release() is called + int i = 0; + { + scope_exit x{[&i]() { i = 1; }}; + } + CHECK(i == 1); + { + scope_exit x{[&i]() { i = 2; }}; + x.release(); + } + CHECK(i == 1); + { + scope_exit x{[&i]() { i += 2; }}; + auto x2 = std::move(x); + } + CHECK(i == 3); + { + scope_exit x{[&i]() { i = 4; }}; + x.release(); + auto x2 = std::move(x); + } + CHECK(i == 3); + { + try + { + scope_exit x{[&i]() { i = 5; }}; + throw 1; + } + catch (...) + { + } + } + CHECK(i == 5); + { + try + { + scope_exit x{[&i]() { i = 6; }}; + x.release(); + throw 1; + } + catch (...) + { + } + } + CHECK(i == 5); +} + +TEST_CASE("scope_fail") +{ + // scope_fail executes the functor on destruction only + // if an exception is unwinding, unless release() is called + int i = 0; + { + scope_fail x{[&i]() { i = 1; }}; + } + CHECK(i == 0); + { + scope_fail x{[&i]() { i = 2; }}; + x.release(); + } + CHECK(i == 0); + { + scope_fail x{[&i]() { i = 3; }}; + auto x2 = std::move(x); + } + CHECK(i == 0); + { + scope_fail x{[&i]() { i = 4; }}; + x.release(); + auto x2 = std::move(x); + } + CHECK(i == 0); + { + try + { + scope_fail x{[&i]() { i = 5; }}; + throw 1; + } + catch (...) + { + } + } + CHECK(i == 5); + { + try + { + scope_fail x{[&i]() { i = 6; }}; + x.release(); + throw 1; + } + catch (...) + { + } + } + CHECK(i == 5); +} + +TEST_CASE("scope_success") +{ + // scope_success executes the functor on destruction only + // if an exception is not unwinding, unless release() is called + int i = 0; + { + scope_success x{[&i]() { i = 1; }}; + } + CHECK(i == 1); + { + scope_success x{[&i]() { i = 2; }}; + x.release(); + } + CHECK(i == 1); + { + scope_success x{[&i]() { i += 2; }}; + auto x2 = std::move(x); + } + CHECK(i == 3); + { + scope_success x{[&i]() { i = 4; }}; + x.release(); + auto x2 = std::move(x); + } + CHECK(i == 3); + { + try + { + scope_success x{[&i]() { i = 5; }}; + throw 1; + } + catch (...) + { + } + } + CHECK(i == 3); + { + try + { + scope_success x{[&i]() { i = 6; }}; + x.release(); + throw 1; + } + catch (...) + { + } + } + CHECK(i == 3); +} diff --git a/src/tests/libxrpl/basics/tagged_integer.cpp b/src/tests/libxrpl/basics/tagged_integer.cpp new file mode 100644 index 0000000000..d699b64a70 --- /dev/null +++ b/src/tests/libxrpl/basics/tagged_integer.cpp @@ -0,0 +1,247 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2014 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include + +#include + +using namespace ripple; + +struct Tag1 +{ +}; +struct Tag2 +{ +}; + +// Static checks that types are not interoperable + +using TagUInt1 = tagged_integer; +using TagUInt2 = tagged_integer; +using TagUInt3 = tagged_integer; + +// Check construction of tagged_integers +static_assert( + std::is_constructible::value, + "TagUInt1 should be constructible using a std::uint32_t"); + +static_assert( + !std::is_constructible::value, + "TagUInt1 should not be constructible using a std::uint64_t"); + +static_assert( + std::is_constructible::value, + "TagUInt3 should be constructible using a std::uint32_t"); + +static_assert( + std::is_constructible::value, + "TagUInt3 should be constructible using a std::uint64_t"); + +// Check assignment of tagged_integers +static_assert( + !std::is_assignable::value, + "TagUInt1 should not be assignable with a std::uint32_t"); + +static_assert( + !std::is_assignable::value, + "TagUInt1 should not be assignable with a std::uint64_t"); + +static_assert( + !std::is_assignable::value, + "TagUInt3 should not be assignable with a std::uint32_t"); + +static_assert( + !std::is_assignable::value, + "TagUInt3 should not be assignable with a std::uint64_t"); + +static_assert( + std::is_assignable::value, + "TagUInt1 should be assignable with a TagUInt1"); + +static_assert( + !std::is_assignable::value, + "TagUInt1 should not be assignable with a TagUInt2"); + +static_assert( + std::is_assignable::value, + "TagUInt3 should be assignable with a TagUInt1"); + +static_assert( + !std::is_assignable::value, + "TagUInt1 should not be assignable with a TagUInt3"); + +static_assert( + !std::is_assignable::value, + "TagUInt3 should not be assignable with a TagUInt1"); + +// Check convertibility of tagged_integers +static_assert( + !std::is_convertible::value, + "std::uint32_t should not be convertible to a TagUInt1"); + +static_assert( + !std::is_convertible::value, + "std::uint32_t should not be convertible to a TagUInt3"); + +static_assert( + !std::is_convertible::value, + "std::uint64_t should not be convertible to a TagUInt3"); + +static_assert( + !std::is_convertible::value, + "std::uint64_t should not be convertible to a TagUInt2"); + +static_assert( + !std::is_convertible::value, + "TagUInt1 should not be convertible to TagUInt2"); + +static_assert( + !std::is_convertible::value, + "TagUInt1 should not be convertible to TagUInt3"); + +static_assert( + !std::is_convertible::value, + "TagUInt2 should not be convertible to a TagUInt3"); + +TEST_SUITE_BEGIN("tagged_integer"); + +using TagInt = tagged_integer; + +TEST_CASE("comparison operators") +{ + TagInt const zero(0); + TagInt const one(1); + + CHECK(one == one); + CHECK(!(one == zero)); + + CHECK(one != zero); + CHECK(!(one != one)); + + CHECK(zero < one); + CHECK(!(one < zero)); + + CHECK(one > zero); + CHECK(!(zero > one)); + + CHECK(one >= one); + CHECK(one >= zero); + CHECK(!(zero >= one)); + + CHECK(zero <= one); + CHECK(zero <= zero); + CHECK(!(one <= zero)); +} + +TEST_CASE("increment / decrement operators") +{ + TagInt const zero(0); + TagInt const one(1); + TagInt a{0}; + ++a; + CHECK(a == one); + --a; + CHECK(a == zero); + a++; + CHECK(a == one); + a--; + CHECK(a == zero); +} + +TEST_CASE("arithmetic operators") +{ + TagInt a{-2}; + CHECK(+a == TagInt{-2}); + CHECK(-a == TagInt{2}); + CHECK(TagInt{-3} + TagInt{4} == TagInt{1}); + CHECK(TagInt{-3} - TagInt{4} == TagInt{-7}); + CHECK(TagInt{-3} * TagInt{4} == TagInt{-12}); + CHECK(TagInt{8} / TagInt{4} == TagInt{2}); + CHECK(TagInt{7} % TagInt{4} == TagInt{3}); + + CHECK(~TagInt{8} == TagInt{~TagInt::value_type{8}}); + CHECK((TagInt{6} & TagInt{3}) == TagInt{2}); + CHECK((TagInt{6} | TagInt{3}) == TagInt{7}); + CHECK((TagInt{6} ^ TagInt{3}) == TagInt{5}); + + CHECK((TagInt{4} << TagInt{2}) == TagInt{16}); + CHECK((TagInt{16} >> TagInt{2}) == TagInt{4}); +} + +TEST_CASE("assignment operators") +{ + TagInt a{-2}; + TagInt b{0}; + b = a; + CHECK(b == TagInt{-2}); + + // -3 + 4 == 1 + a = TagInt{-3}; + a += TagInt{4}; + CHECK(a == TagInt{1}); + + // -3 - 4 == -7 + a = TagInt{-3}; + a -= TagInt{4}; + CHECK(a == TagInt{-7}); + + // -3 * 4 == -12 + a = TagInt{-3}; + a *= TagInt{4}; + CHECK(a == TagInt{-12}); + + // 8/4 == 2 + a = TagInt{8}; + a /= TagInt{4}; + CHECK(a == TagInt{2}); + + // 7 % 4 == 3 + a = TagInt{7}; + a %= TagInt{4}; + CHECK(a == TagInt{3}); + + // 6 & 3 == 2 + a = TagInt{6}; + a /= TagInt{3}; + CHECK(a == TagInt{2}); + + // 6 | 3 == 7 + a = TagInt{6}; + a |= TagInt{3}; + CHECK(a == TagInt{7}); + + // 6 ^ 3 == 5 + a = TagInt{6}; + a ^= TagInt{3}; + CHECK(a == TagInt{5}); + + // 4 << 2 == 16 + a = TagInt{4}; + a <<= TagInt{2}; + CHECK(a == TagInt{16}); + + // 16 >> 2 == 4 + a = TagInt{16}; + a >>= TagInt{2}; + CHECK(a == TagInt{4}); +} + +TEST_SUITE_END(); diff --git a/src/test/core/CryptoPRNG_test.cpp b/src/tests/libxrpl/crypto/csprng.cpp similarity index 58% rename from src/test/core/CryptoPRNG_test.cpp rename to src/tests/libxrpl/crypto/csprng.cpp index 21924e582c..a55d49b67c 100644 --- a/src/test/core/CryptoPRNG_test.cpp +++ b/src/tests/libxrpl/crypto/csprng.cpp @@ -17,44 +17,18 @@ */ //============================================================================== -#include - -#include #include -namespace ripple { +#include -class CryptoPRNG_test : public beast::unit_test::suite +using namespace ripple; + +TEST_CASE("get values") { - void - testGetValues() - { - testcase("Get Values"); - try - { - auto& engine = crypto_prng(); - auto rand_val = engine(); - BEAST_EXPECT(rand_val >= engine.min()); - BEAST_EXPECT(rand_val <= engine.max()); - - uint16_t twoByte{0}; - engine(&twoByte, sizeof(uint16_t)); - pass(); - } - catch (std::exception&) - { - fail(); - } - } - -public: - void - run() override - { - testGetValues(); - } -}; - -BEAST_DEFINE_TESTSUITE(CryptoPRNG, core, ripple); - -} // namespace ripple + auto& engine = crypto_prng(); + auto rand_val = engine(); + CHECK(rand_val >= engine.min()); + CHECK(rand_val <= engine.max()); + uint16_t twoByte{0}; + engine(&twoByte, sizeof(uint16_t)); +} diff --git a/src/tests/libxrpl/crypto/main.cpp b/src/tests/libxrpl/crypto/main.cpp new file mode 100644 index 0000000000..0a3f254ea8 --- /dev/null +++ b/src/tests/libxrpl/crypto/main.cpp @@ -0,0 +1,2 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include