test commit

This commit is contained in:
Pratik Mankawde
2025-12-11 19:04:11 +00:00
parent adc6ca6d11
commit db73390eff
26 changed files with 222 additions and 34 deletions

View File

@@ -1,3 +1,13 @@
doctest.basics > xrpl.basics
doctest.basics > xrpl.protocol
doctest.beast > xrpl.basics
doctest.core > xrpl.core
doctest.core > xrpl.json
doctest.csf > test.csf
doctest.nodestore > xrpl.nodestore
doctest.protocol > xrpl.basics
doctest.protocol > xrpl.json
doctest.protocol > xrpl.protocol
libxrpl.basics > xrpl.basics
libxrpl.core > xrpl.basics
libxrpl.core > xrpl.core

View File

@@ -1,6 +1,8 @@
# CMake configuration for doctest-based tests
# These are converted from the beast unit_test framework
include(XrplAddTest)
find_package(doctest REQUIRED)
# Custom target for all doctest tests defined in this file
@@ -19,30 +21,53 @@ target_include_directories(xrpl.imports.doctest INTERFACE
)
# Link against xrpld libraries for tests that need app-level functionality
# Tests like LoadFeeTrack, PendingSaves need xrpld components
target_link_libraries(xrpl.imports.doctest INTERFACE
Xrpl::boost
Xrpl::opts
Xrpl::libs
)
# Collect all doctest source files
file(GLOB_RECURSE doctest_sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
# Compiler flags for strict checking
set(DOCTEST_COMPILE_FLAGS
-m64
-g
-fPIE
-Wno-unknown-warning-option
-Wall
-Wdeprecated
-Wno-deprecated-declarations
-Wextra
-Wno-unused-parameter
-Werror
-fstack-protector
-Wno-sign-compare
-Wno-unused-but-set-variable
)
# Create the main test executable
add_executable(xrpl.doctest ${doctest_sources})
target_link_libraries(xrpl.doctest PRIVATE xrpl.imports.doctest)
# Helper function to add a doctest module
function(xrpl_add_doctest name)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
)
# Make sure the test isn't optimized away in unity builds
set_target_properties(xrpl.doctest PROPERTIES
UNITY_BUILD_MODE GROUP
UNITY_BUILD_BATCH_SIZE 0
)
set(target xrpl.doctest.${name})
add_executable(${target} ${sources})
target_link_libraries(${target} PRIVATE xrpl.imports.doctest)
target_compile_options(${target} PRIVATE ${DOCTEST_COMPILE_FLAGS})
# Add as a CTest test
add_test(NAME xrpl.doctest COMMAND xrpl.doctest)
set_target_properties(${target} PROPERTIES
UNITY_BUILD_MODE GROUP
UNITY_BUILD_BATCH_SIZE 0
)
add_dependencies(xrpl.doctests xrpl.doctest)
add_test(NAME ${target} COMMAND ${target})
add_dependencies(xrpl.doctests ${target})
endfunction()
# One test executable for each module
xrpl_add_doctest(basics)
xrpl_add_doctest(beast)
xrpl_add_doctest(core)
xrpl_add_doctest(csf)
xrpl_add_doctest(nodestore)
xrpl_add_doctest(protocol)

View File

@@ -130,4 +130,3 @@ TEST_CASE("containers")
}
TEST_SUITE_END();

View File

@@ -75,4 +75,3 @@ TEST_CASE("CollectionAndDelimiter")
}
TEST_SUITE_END();

View File

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

View File

@@ -67,4 +67,3 @@ TEST_CASE("Thread names are preserved")
}
TEST_SUITE_END();

View File

@@ -93,4 +93,3 @@ TEST_CASE("Journal threshold kDebug")
}
TEST_SUITE_END();

View File

@@ -15,4 +15,3 @@ TEST_CASE("basic_seconds_clock::now() works")
}
TEST_SUITE_END();

View File

@@ -96,4 +96,3 @@ TEST_CASE("ADL")
}
TEST_SUITE_END();

View File

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

View File

@@ -166,4 +166,3 @@ TEST_CASE("threadCounts: 64 -> 3 -> 65")
TEST_SUITE_END();
} // namespace xrpl

View File

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

View File

@@ -120,4 +120,3 @@ TEST_CASE("BasicNetwork disconnect")
}
TEST_SUITE_END();

View File

@@ -70,4 +70,3 @@ TEST_CASE("Digraph basic operations")
}
TEST_SUITE_END();

View File

@@ -73,4 +73,3 @@ TEST_CASE("Histogram duplicate elements")
}
TEST_SUITE_END();

View File

@@ -61,4 +61,3 @@ TEST_CASE("Scheduler basic operations")
}
TEST_SUITE_END();

2
src/doctest/csf/main.cpp Normal file
View File

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

View File

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

View File

@@ -44,4 +44,3 @@ TEST_CASE("encode, decode")
}
TEST_SUITE_END();

View File

@@ -35,4 +35,3 @@ TEST_CASE("API versions")
}
TEST_SUITE_END();

View File

@@ -69,7 +69,8 @@ TEST_CASE("STAccount bad size throws")
{
// Construct from a VL that is not exactly 160 bits.
Serializer s;
std::uint8_t const bits128[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
std::uint8_t const bits128[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
s.addVL(bits128, sizeof(bits128));
SerialIter sit(s.slice());
CHECK_THROWS_AS(STAccount(sit, sfAccount), std::runtime_error);
@@ -113,4 +114,3 @@ TEST_CASE("AccountID invalid parsing")
}
TEST_SUITE_END();

View File

@@ -121,4 +121,3 @@ TEST_CASE("Int32")
}
TEST_SUITE_END();

View File

@@ -0,0 +1,160 @@
#include <xrpl/beast/utility/rngfill.h>
#include <xrpl/crypto/csprng.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/SecretKey.h>
#include <xrpl/protocol/Seed.h>
#include <doctest/doctest.h>
#include <algorithm>
#include <string>
#include <vector>
namespace xrpl {
struct TestKeyData
{
std::array<std::uint8_t, 16> seed;
std::array<std::uint8_t, 33> pubkey;
std::array<std::uint8_t, 32> seckey;
char const* addr;
};
using blob = std::vector<std::uint8_t>;
TEST_SUITE_BEGIN("SecretKey");
TEST_CASE("secp256k1: canonicality")
{
std::array<std::uint8_t, 32> const digestData{
0x34, 0xC1, 0x90, 0x28, 0xC8, 0x0D, 0x21, 0xF3, 0xF4, 0x8C, 0x93,
0x54, 0x89, 0x5F, 0x8D, 0x5B, 0xF0, 0xD5, 0xEE, 0x7F, 0xF4, 0x57,
0x64, 0x7C, 0xF6, 0x55, 0xF5, 0x53, 0x0A, 0x30, 0x22, 0xA7};
std::array<std::uint8_t, 33> const pkData{
0x02, 0x50, 0x96, 0xEB, 0x12, 0xD3, 0xE9, 0x24, 0x23, 0x4E, 0x71,
0x62, 0x36, 0x9C, 0x11, 0xD8, 0xBF, 0x87, 0x7E, 0xDA, 0x23, 0x87,
0x78, 0xE7, 0xA3, 0x1F, 0xF0, 0xAA, 0xC5, 0xD0, 0xDB, 0xCF, 0x37};
std::array<std::uint8_t, 32> const skData{
0xAA, 0x92, 0x14, 0x17, 0xE7, 0xE5, 0xC2, 0x99, 0xDA, 0x4E, 0xEC,
0x16, 0xD1, 0xCA, 0xA9, 0x2F, 0x19, 0xB1, 0x9F, 0x2A, 0x68, 0x51,
0x1F, 0x68, 0xEC, 0x73, 0xBB, 0xB2, 0xF5, 0x23, 0x6F, 0x3D};
std::array<std::uint8_t, 71> const sig{
0x30, 0x45, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, 0xBA,
0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, 0x77, 0x91, 0x40, 0x8D, 0x1F, 0xB8,
0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, 0x60, 0xF2, 0x46,
0x60, 0x02, 0x20, 0x50, 0x87, 0x39, 0xDB, 0x0A, 0x2E, 0xF8, 0x16, 0x76,
0xE3, 0x9F, 0x45, 0x9C, 0x8B, 0xBB, 0x07, 0xA0, 0x9C, 0x3E, 0x9F, 0x9B,
0xEB, 0x69, 0x62, 0x94, 0xD5, 0x24, 0xD4, 0x79, 0xD6, 0x27, 0x40};
std::array<std::uint8_t, 72> const non{
0x30, 0x46, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, 0xBA,
0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, 0x77, 0x91, 0x40, 0x8D, 0x1F, 0xB8,
0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, 0x60, 0xF2, 0x46,
0x60, 0x02, 0x21, 0x00, 0xAF, 0x78, 0xC6, 0x24, 0xF5, 0xD1, 0x07, 0xE9,
0x89, 0x1C, 0x60, 0xBA, 0x63, 0x74, 0x44, 0xF7, 0x1A, 0x12, 0x9E, 0x47,
0x13, 0x5D, 0x36, 0xD9, 0x2A, 0xFD, 0x39, 0xB8, 0x56, 0x60, 0x1A, 0x01};
auto const digest = uint256::fromVoid(digestData.data());
PublicKey const pk{makeSlice(pkData)};
SecretKey const sk{makeSlice(skData)};
{
auto const canonicality = ecdsaCanonicality(makeSlice(sig));
CHECK(canonicality);
CHECK(*canonicality == ECDSACanonicality::fullyCanonical);
}
{
auto const canonicality = ecdsaCanonicality(makeSlice(non));
CHECK(canonicality);
CHECK(*canonicality != ECDSACanonicality::fullyCanonical);
}
CHECK(verifyDigest(pk, digest, makeSlice(sig), false));
CHECK(verifyDigest(pk, digest, makeSlice(sig), true));
CHECK(verifyDigest(pk, digest, makeSlice(non), false));
CHECK(!verifyDigest(pk, digest, makeSlice(non), true));
}
TEST_CASE("secp256k1: digest signing & verification")
{
for (std::size_t i = 0; i < 32; i++)
{
auto const [pk, sk] = randomKeyPair(KeyType::secp256k1);
CHECK(pk == derivePublicKey(KeyType::secp256k1, sk));
CHECK(*publicKeyType(pk) == KeyType::secp256k1);
for (std::size_t j = 0; j < 32; j++)
{
uint256 digest;
beast::rngfill(digest.data(), digest.size(), crypto_prng());
auto sig = signDigest(pk, sk, digest);
CHECK(sig.size() != 0);
CHECK(verifyDigest(pk, digest, sig, true));
// Wrong digest:
CHECK(!verifyDigest(pk, ~digest, sig, true));
// Slightly change the signature:
if (auto ptr = sig.data())
ptr[j % sig.size()]++;
// Wrong signature:
CHECK(!verifyDigest(pk, digest, sig, true));
// Wrong digest and signature:
CHECK(!verifyDigest(pk, ~digest, sig, true));
}
}
}
void
testSigning(KeyType type)
{
for (std::size_t i = 0; i < 32; i++)
{
auto const [pk, sk] = randomKeyPair(type);
CHECK(pk == derivePublicKey(type, sk));
CHECK(*publicKeyType(pk) == type);
for (std::size_t j = 0; j < 32; j++)
{
std::vector<std::uint8_t> data(64 + (8 * i) + j);
beast::rngfill(data.data(), data.size(), crypto_prng());
auto sig = sign(pk, sk, makeSlice(data));
CHECK(sig.size() != 0);
CHECK(verify(pk, makeSlice(data), sig));
// Construct wrong data:
auto badData = data;
// swaps the smallest and largest elements in buffer
std::iter_swap(
std::min_element(badData.begin(), badData.end()),
std::max_element(badData.begin(), badData.end()));
// Wrong data: should fail
CHECK(!verify(pk, makeSlice(badData), sig));
// Slightly change the signature:
if (auto ptr = sig.data())
ptr[j % sig.size()]++;
// Wrong signature: should fail
CHECK(!verify(pk, makeSlice(data), sig));
// Wrong data and signature: should fail
CHECK(!verify(pk, makeSlice(badData), sig));
}
}
}

View File

@@ -153,4 +153,3 @@ TEST_CASE("SeqProxy operations")
}
TEST_SUITE_END();

View File

@@ -45,4 +45,3 @@ TEST_CASE("Serializer add64/geti64")
}
TEST_SUITE_END();

View File

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