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.
This commit is contained in:
Vlad
2025-06-26 20:35:31 +01:00
committed by GitHub
parent df6daf0d8f
commit e18f27f5f7
25 changed files with 908 additions and 927 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

41
cmake/xrpl_add_test.cmake Normal file
View File

@@ -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 $<CONFIG>
--target ${target}
)
set_tests_properties(${target}.build PROPERTIES
FIXTURES_SETUP ${target}_fixture
)
endfunction()

View File

@@ -24,6 +24,7 @@ class Xrpl(ConanFile):
}
requires = [
'doctest/2.4.11',
'grpc/1.50.1',
'libarchive/3.7.6',
'nudb/2.0.8',

View File

@@ -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 <xrpl/basics/RangeSet.h>
#include <xrpl/beast/unit_test.h>
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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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

View File

@@ -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 <xrpl/basics/Slice.h>
#include <xrpl/beast/unit_test.h>
#include <array>
#include <cstdint>
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<std::uint8_t, sizeof(data)> a;
std::array<std::uint8_t, sizeof(data)> 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

View File

@@ -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 <xrpl/basics/base64.h>
#include <xrpl/beast/unit_test.h>
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

View File

@@ -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 <xrpl/basics/mulDiv.h>
#include <xrpl/beast/unit_test.h>
namespace ripple {
namespace test {
struct mulDiv_test : beast::unit_test::suite
{
void
run() override
{
auto const max = std::numeric_limits<std::uint64_t>::max();
std::uint64_t const max32 = std::numeric_limits<std::uint32_t>::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

View File

@@ -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 <xrpl/basics/scope.h>
#include <xrpl/beast/unit_test.h>
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

View File

@@ -1,258 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright 2014, Nikolaos D. Bougalis <nikb@bougalis.net>
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 <xrpl/basics/tagged_integer.h>
#include <xrpl/beast/unit_test.h>
#include <type_traits>
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<std::uint32_t, Tag1>;
using TagUInt2 = tagged_integer<std::uint32_t, Tag2>;
using TagUInt3 = tagged_integer<std::uint64_t, Tag1>;
// Check construction of tagged_integers
static_assert(
std::is_constructible<TagUInt1, std::uint32_t>::value,
"TagUInt1 should be constructible using a std::uint32_t");
static_assert(
!std::is_constructible<TagUInt1, std::uint64_t>::value,
"TagUInt1 should not be constructible using a std::uint64_t");
static_assert(
std::is_constructible<TagUInt3, std::uint32_t>::value,
"TagUInt3 should be constructible using a std::uint32_t");
static_assert(
std::is_constructible<TagUInt3, std::uint64_t>::value,
"TagUInt3 should be constructible using a std::uint64_t");
// Check assignment of tagged_integers
static_assert(
!std::is_assignable<TagUInt1, std::uint32_t>::value,
"TagUInt1 should not be assignable with a std::uint32_t");
static_assert(
!std::is_assignable<TagUInt1, std::uint64_t>::value,
"TagUInt1 should not be assignable with a std::uint64_t");
static_assert(
!std::is_assignable<TagUInt3, std::uint32_t>::value,
"TagUInt3 should not be assignable with a std::uint32_t");
static_assert(
!std::is_assignable<TagUInt3, std::uint64_t>::value,
"TagUInt3 should not be assignable with a std::uint64_t");
static_assert(
std::is_assignable<TagUInt1, TagUInt1>::value,
"TagUInt1 should be assignable with a TagUInt1");
static_assert(
!std::is_assignable<TagUInt1, TagUInt2>::value,
"TagUInt1 should not be assignable with a TagUInt2");
static_assert(
std::is_assignable<TagUInt3, TagUInt3>::value,
"TagUInt3 should be assignable with a TagUInt1");
static_assert(
!std::is_assignable<TagUInt1, TagUInt3>::value,
"TagUInt1 should not be assignable with a TagUInt3");
static_assert(
!std::is_assignable<TagUInt3, TagUInt1>::value,
"TagUInt3 should not be assignable with a TagUInt1");
// Check convertibility of tagged_integers
static_assert(
!std::is_convertible<std::uint32_t, TagUInt1>::value,
"std::uint32_t should not be convertible to a TagUInt1");
static_assert(
!std::is_convertible<std::uint32_t, TagUInt3>::value,
"std::uint32_t should not be convertible to a TagUInt3");
static_assert(
!std::is_convertible<std::uint64_t, TagUInt3>::value,
"std::uint64_t should not be convertible to a TagUInt3");
static_assert(
!std::is_convertible<std::uint64_t, TagUInt2>::value,
"std::uint64_t should not be convertible to a TagUInt2");
static_assert(
!std::is_convertible<TagUInt1, TagUInt2>::value,
"TagUInt1 should not be convertible to TagUInt2");
static_assert(
!std::is_convertible<TagUInt1, TagUInt3>::value,
"TagUInt1 should not be convertible to TagUInt3");
static_assert(
!std::is_convertible<TagUInt2, TagUInt3>::value,
"TagUInt2 should not be convertible to a TagUInt3");
public:
void
run() override
{
using TagInt = tagged_integer<std::int32_t, Tag1>;
{
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

4
src/tests/README.md Normal file
View File

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

View File

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

View File

@@ -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 <xrpl/basics/RangeSet.h>
#include <doctest/doctest.h>
#include <cstdint>
#include <optional>
using namespace ripple;
TEST_SUITE_BEGIN("RangeSet");
TEST_CASE("prevMissing")
{
// Set will include:
// [ 0, 5]
// [10,15]
// [20,25]
// etc...
RangeSet<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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();

View File

@@ -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 <xrpl/basics/Slice.h>
#include <doctest/doctest.h>
#include <array>
#include <cstdint>
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<std::uint8_t, sizeof(data)> a;
std::array<std::uint8_t, sizeof(data)> 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();

View File

@@ -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 <xrpl/basics/base64.h>
#include <doctest/doctest.h>
#include <string>
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));
}

View File

@@ -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,25 +18,23 @@
//==============================================================================
#include <xrpl/basics/contract.h>
#include <xrpl/beast/unit_test.h>
#include <doctest/doctest.h>
#include <stdexcept>
#include <string>
namespace ripple {
using namespace ripple;
class contract_test : public beast::unit_test::suite
TEST_CASE("contract")
{
public:
void
run() override
{
try
{
Throw<std::runtime_error>("Throw test");
}
catch (std::runtime_error const& e1)
{
BEAST_EXPECT(std::string(e1.what()) == "Throw test");
CHECK(std::string(e1.what()) == "Throw test");
try
{
@@ -44,20 +42,15 @@ public:
}
catch (std::runtime_error const& e2)
{
BEAST_EXPECT(std::string(e2.what()) == "Throw test");
CHECK(std::string(e2.what()) == "Throw test");
}
catch (...)
{
BEAST_EXPECT(false);
CHECK(false);
}
}
catch (...)
{
BEAST_EXPECT(false);
CHECK(false);
}
}
};
BEAST_DEFINE_TESTSUITE(contract, basics, ripple);
} // namespace ripple
}

View File

@@ -0,0 +1,2 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

View File

@@ -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 <xrpl/basics/mulDiv.h>
#include <doctest/doctest.h>
#include <cstdint>
#include <limits>
using namespace ripple;
TEST_CASE("mulDiv")
{
auto const max = std::numeric_limits<std::uint64_t>::max();
std::uint64_t const max32 = std::numeric_limits<std::uint32_t>::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);
}

View File

@@ -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 <xrpl/basics/scope.h>
#include <doctest/doctest.h>
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);
}

View File

@@ -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 <xrpl/basics/tagged_integer.h>
#include <doctest/doctest.h>
#include <type_traits>
using namespace ripple;
struct Tag1
{
};
struct Tag2
{
};
// Static checks that types are not interoperable
using TagUInt1 = tagged_integer<std::uint32_t, Tag1>;
using TagUInt2 = tagged_integer<std::uint32_t, Tag2>;
using TagUInt3 = tagged_integer<std::uint64_t, Tag1>;
// Check construction of tagged_integers
static_assert(
std::is_constructible<TagUInt1, std::uint32_t>::value,
"TagUInt1 should be constructible using a std::uint32_t");
static_assert(
!std::is_constructible<TagUInt1, std::uint64_t>::value,
"TagUInt1 should not be constructible using a std::uint64_t");
static_assert(
std::is_constructible<TagUInt3, std::uint32_t>::value,
"TagUInt3 should be constructible using a std::uint32_t");
static_assert(
std::is_constructible<TagUInt3, std::uint64_t>::value,
"TagUInt3 should be constructible using a std::uint64_t");
// Check assignment of tagged_integers
static_assert(
!std::is_assignable<TagUInt1, std::uint32_t>::value,
"TagUInt1 should not be assignable with a std::uint32_t");
static_assert(
!std::is_assignable<TagUInt1, std::uint64_t>::value,
"TagUInt1 should not be assignable with a std::uint64_t");
static_assert(
!std::is_assignable<TagUInt3, std::uint32_t>::value,
"TagUInt3 should not be assignable with a std::uint32_t");
static_assert(
!std::is_assignable<TagUInt3, std::uint64_t>::value,
"TagUInt3 should not be assignable with a std::uint64_t");
static_assert(
std::is_assignable<TagUInt1, TagUInt1>::value,
"TagUInt1 should be assignable with a TagUInt1");
static_assert(
!std::is_assignable<TagUInt1, TagUInt2>::value,
"TagUInt1 should not be assignable with a TagUInt2");
static_assert(
std::is_assignable<TagUInt3, TagUInt3>::value,
"TagUInt3 should be assignable with a TagUInt1");
static_assert(
!std::is_assignable<TagUInt1, TagUInt3>::value,
"TagUInt1 should not be assignable with a TagUInt3");
static_assert(
!std::is_assignable<TagUInt3, TagUInt1>::value,
"TagUInt3 should not be assignable with a TagUInt1");
// Check convertibility of tagged_integers
static_assert(
!std::is_convertible<std::uint32_t, TagUInt1>::value,
"std::uint32_t should not be convertible to a TagUInt1");
static_assert(
!std::is_convertible<std::uint32_t, TagUInt3>::value,
"std::uint32_t should not be convertible to a TagUInt3");
static_assert(
!std::is_convertible<std::uint64_t, TagUInt3>::value,
"std::uint64_t should not be convertible to a TagUInt3");
static_assert(
!std::is_convertible<std::uint64_t, TagUInt2>::value,
"std::uint64_t should not be convertible to a TagUInt2");
static_assert(
!std::is_convertible<TagUInt1, TagUInt2>::value,
"TagUInt1 should not be convertible to TagUInt2");
static_assert(
!std::is_convertible<TagUInt1, TagUInt3>::value,
"TagUInt1 should not be convertible to TagUInt3");
static_assert(
!std::is_convertible<TagUInt2, TagUInt3>::value,
"TagUInt2 should not be convertible to a TagUInt3");
TEST_SUITE_BEGIN("tagged_integer");
using TagInt = tagged_integer<std::int32_t, Tag1>;
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();

View File

@@ -17,44 +17,18 @@
*/
//==============================================================================
#include <test/jtx/Env.h>
#include <xrpl/beast/utility/temp_dir.h>
#include <xrpl/crypto/csprng.h>
namespace ripple {
#include <doctest/doctest.h>
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());
CHECK(rand_val >= engine.min());
CHECK(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
}

View File

@@ -0,0 +1,2 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>