mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-30 18:40:28 +00:00
Merge branch 'pratik/otel-phase10-workload-validation' into pratik/perf-test-otel-on
This commit is contained in:
@@ -75,6 +75,8 @@ Checks: "-*,
|
||||
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
|
||||
# ---
|
||||
|
||||
FormatStyle: file
|
||||
|
||||
CheckOptions:
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
|
||||
@@ -185,7 +185,6 @@ words:
|
||||
- mcmodel
|
||||
- MEMORYSTATUSEX
|
||||
- Merkle
|
||||
- Metafuncton
|
||||
- misprediction
|
||||
- missingok
|
||||
- MPTAMM
|
||||
|
||||
@@ -266,7 +266,7 @@ jobs:
|
||||
./xrpld --definitions | python3 -m json.tool >server_definitions.json
|
||||
|
||||
- name: Upload server definitions
|
||||
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
|
||||
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: server-definitions
|
||||
|
||||
2
.github/workflows/reusable-clang-tidy.yml
vendored
2
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -95,7 +95,7 @@ jobs:
|
||||
TARGETS: ${{ needs.determine-files.outputs.need_full_run != 'true' && needs.determine-files.outputs.cpp_changed_files || 'include src tests' }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -format -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
|
||||
- name: Print filtered clang-tidy errors
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
|
||||
@@ -348,12 +348,14 @@ run-clang-tidy -p build -allow-no-checks src tests
|
||||
```
|
||||
|
||||
This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory.
|
||||
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
|
||||
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix -format` to the above command:
|
||||
|
||||
```
|
||||
run-clang-tidy -p build -quiet -fix -allow-no-checks src tests
|
||||
run-clang-tidy -p build -quiet -fix -format -allow-no-checks src tests
|
||||
```
|
||||
|
||||
`-format` reformats the fixed code with [`.clang-format`](./.clang-format); without it the fixes are inserted in LLVM style and the `clang-format` hook rewrites them afterwards.
|
||||
|
||||
## Telemetry span attribute naming
|
||||
|
||||
OpenTelemetry span attribute keys follow these rules so they stay consistent
|
||||
|
||||
@@ -144,7 +144,11 @@ def main():
|
||||
+ files
|
||||
)
|
||||
canonicalize_fix_paths(Path(fixes_dir))
|
||||
applied = subprocess.run([clang_apply_replacements, fixes_dir])
|
||||
# `FormatStyle` in .clang-tidy does not reach this path,
|
||||
# so ask for the repository style here.
|
||||
applied = subprocess.run(
|
||||
[clang_apply_replacements, "--format", "--style=file", fixes_dir]
|
||||
)
|
||||
|
||||
return result.returncode or applied.returncode
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ namespace beast {
|
||||
class SemanticVersion
|
||||
{
|
||||
public:
|
||||
using identifier_list = std::vector<std::string>;
|
||||
using IdentifierList = std::vector<std::string>;
|
||||
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
int patchVersion;
|
||||
|
||||
identifier_list preReleaseIdentifiers;
|
||||
identifier_list metaData;
|
||||
IdentifierList preReleaseIdentifiers;
|
||||
IdentifierList metaData;
|
||||
|
||||
SemanticVersion();
|
||||
|
||||
|
||||
@@ -13,18 +13,18 @@ namespace xrpl::node_store {
|
||||
// https://developers.google.com/protocol-buffers/docs/encoding#varints
|
||||
|
||||
// field tag
|
||||
struct varint;
|
||||
struct Varint;
|
||||
|
||||
// Metafuncton to return largest
|
||||
// Metafunction to return largest
|
||||
// possible size of T represented as varint.
|
||||
// T must be unsigned
|
||||
template <class T, bool = std::is_unsigned_v<T>>
|
||||
struct varint_traits;
|
||||
struct VarintTraits;
|
||||
|
||||
template <class T>
|
||||
struct varint_traits<T, true>
|
||||
struct VarintTraits<T, true>
|
||||
{
|
||||
explicit varint_traits() = default;
|
||||
explicit VarintTraits() = default;
|
||||
|
||||
static constexpr std::size_t kMax = ((8 * sizeof(T)) + 6) / 7;
|
||||
};
|
||||
@@ -104,7 +104,7 @@ writeVarint(void* p0, std::size_t v)
|
||||
template <class T>
|
||||
void
|
||||
read(nudb::detail::istream& is, std::size_t& u)
|
||||
requires(std::is_same_v<T, varint>)
|
||||
requires(std::is_same_v<T, Varint>)
|
||||
{
|
||||
auto p0 = is(1);
|
||||
auto p1 = p0;
|
||||
@@ -118,7 +118,7 @@ read(nudb::detail::istream& is, std::size_t& u)
|
||||
template <class T>
|
||||
void
|
||||
write(nudb::detail::ostream& os, std::size_t t)
|
||||
requires(std::is_same_v<T, varint>)
|
||||
requires(std::is_same_v<T, Varint>)
|
||||
{
|
||||
writeVarint(os.data(sizeVarint(t)), t);
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/detail/varint.h>
|
||||
#include <xrpl/nodestore/detail/Varint.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
|
||||
#include <nudb/detail/field.hpp>
|
||||
@@ -59,7 +59,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
using std::runtime_error;
|
||||
using namespace nudb::detail;
|
||||
std::pair<void const*, std::size_t> result;
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
|
||||
auto const n = writeVarint(vi.data(), inSize);
|
||||
auto const outMax = LZ4_compressBound(inSize);
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
|
||||
@@ -240,7 +240,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
|
||||
result.first = out;
|
||||
ostream os(out, result.second);
|
||||
write<varint>(os, type);
|
||||
write<Varint>(os, type);
|
||||
write<std::uint16_t>(os, mask);
|
||||
write(os, vh.data(), n * 32);
|
||||
return result;
|
||||
@@ -252,13 +252,13 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
|
||||
result.first = out;
|
||||
ostream os(out, result.second);
|
||||
write<varint>(os, type);
|
||||
write<Varint>(os, type);
|
||||
write(os, vh.data(), n * 32);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
|
||||
|
||||
static constexpr std::size_t kCodecType = 1;
|
||||
auto const vn = writeVarint(vi.data(), kCodecType);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace beast {
|
||||
|
||||
std::string
|
||||
printIdentifiers(SemanticVersion::identifier_list const& list)
|
||||
printIdentifiers(SemanticVersion::IdentifierList const& list)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
@@ -115,7 +115,7 @@ extractIdentifier(std::string& value, bool allowLeadingZeroes, std::string& inpu
|
||||
|
||||
bool
|
||||
extractIdentifiers(
|
||||
SemanticVersion::identifier_list& identifiers,
|
||||
SemanticVersion::IdentifierList& identifiers,
|
||||
bool allowLeadingZeroes,
|
||||
std::string& input)
|
||||
{
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
#include <xrpl/beast/core/SemanticVersion.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class SemanticVersion_test : public unit_test::Suite
|
||||
{
|
||||
using identifier_list = SemanticVersion::identifier_list;
|
||||
|
||||
public:
|
||||
void
|
||||
checkPass(std::string const& input, bool shouldPass = true)
|
||||
{
|
||||
SemanticVersion v;
|
||||
|
||||
if (shouldPass)
|
||||
{
|
||||
BEAST_EXPECT(v.parse(input));
|
||||
BEAST_EXPECT(v.print() == input);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECT(!v.parse(input));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkFail(std::string const& input)
|
||||
{
|
||||
checkPass(input, false);
|
||||
}
|
||||
|
||||
// check input and input with appended metadata
|
||||
void
|
||||
checkMeta(std::string const& input, bool shouldPass)
|
||||
{
|
||||
checkPass(input, shouldPass);
|
||||
|
||||
checkPass(input + "+a", shouldPass);
|
||||
checkPass(input + "+1", shouldPass);
|
||||
checkPass(input + "+a.b", shouldPass);
|
||||
checkPass(input + "+ab.cd", shouldPass);
|
||||
|
||||
checkFail(input + "!");
|
||||
checkFail(input + "+");
|
||||
checkFail(input + "++");
|
||||
checkFail(input + "+!");
|
||||
checkFail(input + "+.");
|
||||
checkFail(input + "+a.!");
|
||||
}
|
||||
|
||||
void
|
||||
checkMetaFail(std::string const& input)
|
||||
{
|
||||
checkMeta(input, false);
|
||||
}
|
||||
|
||||
// check input, input with appended release data,
|
||||
// input with appended metadata, and input with both
|
||||
// appended release data and appended metadata
|
||||
//
|
||||
void
|
||||
checkRelease(std::string const& input, bool shouldPass = true)
|
||||
{
|
||||
checkMeta(input, shouldPass);
|
||||
|
||||
checkMeta(input + "-1", shouldPass);
|
||||
checkMeta(input + "-a", shouldPass);
|
||||
checkMeta(input + "-a1", shouldPass);
|
||||
checkMeta(input + "-a1.b1", shouldPass);
|
||||
checkMeta(input + "-ab.cd", shouldPass);
|
||||
checkMeta(input + "--", shouldPass);
|
||||
|
||||
checkMetaFail(input + "+");
|
||||
checkMetaFail(input + "!");
|
||||
checkMetaFail(input + "-");
|
||||
checkMetaFail(input + "-!");
|
||||
checkMetaFail(input + "-.");
|
||||
checkMetaFail(input + "-a.!");
|
||||
checkMetaFail(input + "-0.a");
|
||||
}
|
||||
|
||||
// Checks the major.minor.version string alone and with all
|
||||
// possible combinations of release identifiers and metadata.
|
||||
//
|
||||
void
|
||||
check(std::string const& input, bool shouldPass = true)
|
||||
{
|
||||
checkRelease(input, shouldPass);
|
||||
}
|
||||
|
||||
void
|
||||
negcheck(std::string const& input)
|
||||
{
|
||||
check(input, false);
|
||||
}
|
||||
|
||||
void
|
||||
testParse()
|
||||
{
|
||||
testcase("parsing");
|
||||
|
||||
check("0.0.0");
|
||||
check("1.2.3");
|
||||
check("2147483647.2147483647.2147483647"); // max int
|
||||
|
||||
// negative values
|
||||
negcheck("-1.2.3");
|
||||
negcheck("1.-2.3");
|
||||
negcheck("1.2.-3");
|
||||
|
||||
// missing parts
|
||||
negcheck("");
|
||||
negcheck("1");
|
||||
negcheck("1.");
|
||||
negcheck("1.2");
|
||||
negcheck("1.2.");
|
||||
negcheck(".2.3");
|
||||
|
||||
// whitespace
|
||||
negcheck(" 1.2.3");
|
||||
negcheck("1 .2.3");
|
||||
negcheck("1.2 .3");
|
||||
negcheck("1.2.3 ");
|
||||
|
||||
// leading zeroes
|
||||
negcheck("01.2.3");
|
||||
negcheck("1.02.3");
|
||||
negcheck("1.2.03");
|
||||
}
|
||||
|
||||
static identifier_list
|
||||
ids()
|
||||
{
|
||||
return identifier_list();
|
||||
}
|
||||
|
||||
static identifier_list
|
||||
ids(std::string const& s1)
|
||||
{
|
||||
identifier_list v;
|
||||
v.push_back(s1);
|
||||
return v;
|
||||
}
|
||||
|
||||
static identifier_list
|
||||
ids(std::string const& s1, std::string const& s2)
|
||||
{
|
||||
identifier_list v;
|
||||
v.push_back(s1);
|
||||
v.push_back(s2);
|
||||
return v;
|
||||
}
|
||||
|
||||
static identifier_list
|
||||
ids(std::string const& s1, std::string const& s2, std::string const& s3)
|
||||
{
|
||||
identifier_list v;
|
||||
v.push_back(s1);
|
||||
v.push_back(s2);
|
||||
v.push_back(s3);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Checks the decomposition of the input into appropriate values
|
||||
void
|
||||
checkValues(
|
||||
std::string const& input,
|
||||
int majorVersion,
|
||||
int minorVersion,
|
||||
int patchVersion,
|
||||
identifier_list const& preReleaseIdentifiers = identifier_list(),
|
||||
identifier_list const& metaData = identifier_list())
|
||||
{
|
||||
SemanticVersion v;
|
||||
|
||||
BEAST_EXPECT(v.parse(input));
|
||||
|
||||
BEAST_EXPECT(v.majorVersion == majorVersion);
|
||||
BEAST_EXPECT(v.minorVersion == minorVersion);
|
||||
BEAST_EXPECT(v.patchVersion == patchVersion);
|
||||
|
||||
BEAST_EXPECT(v.preReleaseIdentifiers == preReleaseIdentifiers);
|
||||
BEAST_EXPECT(v.metaData == metaData);
|
||||
}
|
||||
|
||||
void
|
||||
testValues()
|
||||
{
|
||||
testcase("values");
|
||||
|
||||
checkValues("0.1.2", 0, 1, 2);
|
||||
checkValues("1.2.3", 1, 2, 3);
|
||||
checkValues("1.2.3-rc1", 1, 2, 3, ids("rc1"));
|
||||
checkValues("1.2.3-rc1.debug", 1, 2, 3, ids("rc1", "debug"));
|
||||
checkValues("1.2.3-rc1.debug.asm", 1, 2, 3, ids("rc1", "debug", "asm"));
|
||||
checkValues("1.2.3+full", 1, 2, 3, ids(), ids("full"));
|
||||
checkValues("1.2.3+full.prod", 1, 2, 3, ids(), ids("full", "prod"));
|
||||
checkValues("1.2.3+full.prod.x86", 1, 2, 3, ids(), ids("full", "prod", "x86"));
|
||||
checkValues(
|
||||
"1.2.3-rc1.debug.asm+full.prod.x86",
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
ids("rc1", "debug", "asm"),
|
||||
ids("full", "prod", "x86"));
|
||||
}
|
||||
|
||||
// makes sure the left version is less than the right
|
||||
void
|
||||
checkLessInternal(std::string const& lhs, std::string const& rhs)
|
||||
{
|
||||
SemanticVersion left;
|
||||
SemanticVersion right;
|
||||
|
||||
BEAST_EXPECT(left.parse(lhs));
|
||||
BEAST_EXPECT(right.parse(rhs));
|
||||
|
||||
BEAST_EXPECT(compare(left, left) == 0);
|
||||
BEAST_EXPECT(compare(right, right) == 0);
|
||||
BEAST_EXPECT(compare(left, right) < 0);
|
||||
BEAST_EXPECT(compare(right, left) > 0);
|
||||
|
||||
BEAST_EXPECT(left < right);
|
||||
BEAST_EXPECT(right > left);
|
||||
BEAST_EXPECT(left == left);
|
||||
BEAST_EXPECT(right == right);
|
||||
}
|
||||
|
||||
void
|
||||
checkLess(std::string const& lhs, std::string const& rhs)
|
||||
{
|
||||
checkLessInternal(lhs, rhs);
|
||||
checkLessInternal(lhs + "+meta", rhs);
|
||||
checkLessInternal(lhs, rhs + "+meta");
|
||||
checkLessInternal(lhs + "+meta", rhs + "+meta");
|
||||
}
|
||||
|
||||
void
|
||||
testCompare()
|
||||
{
|
||||
testcase("comparisons");
|
||||
|
||||
checkLess("1.0.0-alpha", "1.0.0-alpha.1");
|
||||
checkLess("1.0.0-alpha.1", "1.0.0-alpha.beta");
|
||||
checkLess("1.0.0-alpha.beta", "1.0.0-beta");
|
||||
checkLess("1.0.0-beta", "1.0.0-beta.2");
|
||||
checkLess("1.0.0-beta.2", "1.0.0-beta.11");
|
||||
checkLess("1.0.0-beta.11", "1.0.0-rc.1");
|
||||
checkLess("1.0.0-rc.1", "1.0.0");
|
||||
checkLess("0.9.9", "1.0.0");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testParse();
|
||||
testValues();
|
||||
testCompare();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(SemanticVersion, beast, beast);
|
||||
} // namespace beast
|
||||
@@ -1,115 +0,0 @@
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
struct AdlTester
|
||||
{
|
||||
};
|
||||
|
||||
int
|
||||
signum(AdlTester)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace inner_adl_test {
|
||||
|
||||
struct AdlTester2
|
||||
{
|
||||
};
|
||||
|
||||
int
|
||||
signum(AdlTester2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace inner_adl_test
|
||||
|
||||
class Zero_test : public beast::unit_test::Suite
|
||||
{
|
||||
private:
|
||||
struct IntegerWrapper
|
||||
{
|
||||
int value;
|
||||
|
||||
IntegerWrapper(int v) : value(v)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] int
|
||||
signum() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void
|
||||
expectSame(bool result, bool correct, char const* message)
|
||||
{
|
||||
expect(result == correct, message);
|
||||
}
|
||||
|
||||
void
|
||||
testLhsZero(IntegerWrapper x)
|
||||
{
|
||||
expectSame(x >= kZero, x.signum() >= 0, "lhs greater-than-or-equal-to");
|
||||
expectSame(x > kZero, x.signum() > 0, "lhs greater than");
|
||||
expectSame(x == kZero, x.signum() == 0, "lhs equal to");
|
||||
expectSame(x != kZero, x.signum() != 0, "lhs not equal to");
|
||||
expectSame(x < kZero, x.signum() < 0, "lhs less than");
|
||||
expectSame(x <= kZero, x.signum() <= 0, "lhs less-than-or-equal-to");
|
||||
}
|
||||
|
||||
void
|
||||
testLhsZero()
|
||||
{
|
||||
testcase("lhs zero");
|
||||
|
||||
testLhsZero(-7);
|
||||
testLhsZero(0);
|
||||
testLhsZero(32);
|
||||
}
|
||||
|
||||
void
|
||||
testRhsZero(IntegerWrapper x)
|
||||
{
|
||||
expectSame(kZero >= x, 0 >= x.signum(), "rhs greater-than-or-equal-to");
|
||||
expectSame(kZero > x, 0 > x.signum(), "rhs greater than");
|
||||
expectSame(kZero == x, 0 == x.signum(), "rhs equal to");
|
||||
expectSame(kZero != x, 0 != x.signum(), "rhs not equal to");
|
||||
expectSame(kZero < x, 0 < x.signum(), "rhs less than");
|
||||
expectSame(kZero <= x, 0 <= x.signum(), "rhs less-than-or-equal-to");
|
||||
}
|
||||
|
||||
void
|
||||
testRhsZero()
|
||||
{
|
||||
testcase("rhs zero");
|
||||
|
||||
testRhsZero(-4);
|
||||
testRhsZero(0);
|
||||
testRhsZero(64);
|
||||
}
|
||||
|
||||
void
|
||||
testAdl()
|
||||
{
|
||||
expect(AdlTester{} == kZero, "ADL failure!");
|
||||
expect(inner_adl_test::AdlTester2{} == kZero, "ADL failure!");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testLhsZero();
|
||||
testRhsZero();
|
||||
testAdl();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Zero, beast, beast);
|
||||
|
||||
} // namespace beast
|
||||
@@ -1,41 +0,0 @@
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/protocol/ApiVersion.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
struct ApiVersion_test : beast::unit_test::Suite
|
||||
{
|
||||
void
|
||||
run() override
|
||||
{
|
||||
{
|
||||
testcase("API versions invariants");
|
||||
|
||||
static_assert(RPC::kApiMinimumSupportedVersion <= RPC::kApiMaximumSupportedVersion);
|
||||
static_assert(RPC::kApiMinimumSupportedVersion <= RPC::kApiMaximumValidVersion);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion <= RPC::kApiMaximumValidVersion);
|
||||
static_assert(RPC::kApiBetaVersion <= RPC::kApiMaximumValidVersion);
|
||||
|
||||
BEAST_EXPECT(true);
|
||||
}
|
||||
|
||||
{
|
||||
// Update when we change versions
|
||||
testcase("API versions");
|
||||
|
||||
static_assert(RPC::kApiMinimumSupportedVersion >= 1);
|
||||
static_assert(RPC::kApiMinimumSupportedVersion < 2);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion >= 2);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion < 3);
|
||||
static_assert(RPC::kApiMaximumValidVersion >= 3);
|
||||
static_assert(RPC::kApiMaximumValidVersion < 4);
|
||||
static_assert(RPC::kApiBetaVersion >= 3);
|
||||
static_assert(RPC::kApiBetaVersion < 4);
|
||||
|
||||
BEAST_EXPECT(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(ApiVersion, protocol, xrpl);
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -1,52 +0,0 @@
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
struct Serializer_test : public beast::unit_test::Suite
|
||||
{
|
||||
void
|
||||
run() override
|
||||
{
|
||||
{
|
||||
std::initializer_list<std::int32_t> const values = {
|
||||
std::numeric_limits<std::int32_t>::min(),
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
std::numeric_limits<std::int32_t>::max()};
|
||||
for (std::int32_t const value : values)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(value);
|
||||
BEAST_EXPECT(s.size() == 4);
|
||||
SerialIter sit(s.slice());
|
||||
BEAST_EXPECT(sit.geti32() == value);
|
||||
}
|
||||
}
|
||||
{
|
||||
std::initializer_list<std::int64_t> const values = {
|
||||
std::numeric_limits<std::int64_t>::min(),
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
std::numeric_limits<std::int64_t>::max()};
|
||||
for (std::int64_t const value : values)
|
||||
{
|
||||
Serializer s;
|
||||
s.add64(value);
|
||||
BEAST_EXPECT(s.size() == 8);
|
||||
SerialIter sit(s.slice());
|
||||
BEAST_EXPECT(sit.geti64() == value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Serializer, protocol, xrpl);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -32,16 +32,18 @@ target_link_libraries(xrpl_tests PRIVATE GTest::gtest GTest::gmock xrpl.libxrpl)
|
||||
# supported on Windows.
|
||||
set(test_modules
|
||||
basics
|
||||
beast
|
||||
consensus
|
||||
crypto
|
||||
json
|
||||
ledger
|
||||
nodestore
|
||||
peerfinder
|
||||
protocol
|
||||
resource
|
||||
shamap
|
||||
tx
|
||||
protocol_autogen
|
||||
nodestore
|
||||
telemetry
|
||||
)
|
||||
if(NOT WIN32)
|
||||
|
||||
333
src/tests/libxrpl/beast/SemanticVersion.cpp
Normal file
333
src/tests/libxrpl/beast/SemanticVersion.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
#include <xrpl/beast/core/SemanticVersion.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace {
|
||||
|
||||
using IdentifierList = SemanticVersion::IdentifierList;
|
||||
|
||||
// Version strings are not valid C++ identifiers, so squash their punctuation to
|
||||
// turn one into a gtest parameter name.
|
||||
std::string
|
||||
identifierFor(std::string_view version)
|
||||
{
|
||||
std::string name{version};
|
||||
std::ranges::replace_if(
|
||||
name, [](char c) { return !std::isalnum(c, std::locale::classic()); }, '_');
|
||||
if (!name.empty() && std::isdigit(name.front(), std::locale::classic()))
|
||||
name.insert(0, "v_");
|
||||
return name;
|
||||
}
|
||||
|
||||
// Pre-release and metadata suffixes, each applied to a "major.minor.patch" base.
|
||||
// The valid ones leave a well-formed base well-formed; the invalid ones make any
|
||||
// base malformed.
|
||||
constexpr auto kValidPreRelease =
|
||||
std::to_array<std::string_view>({"", "-1", "-a", "-a1", "-a1.b1", "-ab.cd", "--"});
|
||||
constexpr auto kInvalidPreRelease =
|
||||
std::to_array<std::string_view>({"+", "!", "-", "-!", "-.", "-a.!", "-0.a"});
|
||||
constexpr auto kValidMetaData = std::to_array<std::string_view>({"", "+a", "+1", "+a.b", "+ab.cd"});
|
||||
constexpr auto kInvalidMetaData =
|
||||
std::to_array<std::string_view>({"!", "+", "++", "+!", "+.", "+a.!"});
|
||||
|
||||
// Assembles base + preRelease + metaData and checks whether it parses. A version
|
||||
// we accept must also round-trip through print().
|
||||
void
|
||||
expectParse(
|
||||
std::string_view base,
|
||||
std::string_view preRelease,
|
||||
std::string_view metaData,
|
||||
bool shouldPass)
|
||||
{
|
||||
auto const input = std::string{base}.append(preRelease).append(metaData);
|
||||
SCOPED_TRACE(::testing::Message() << '"' << input << '"');
|
||||
|
||||
SemanticVersion v;
|
||||
|
||||
if (shouldPass)
|
||||
{
|
||||
EXPECT_TRUE(v.parse(input));
|
||||
EXPECT_EQ(v.print(), input);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_FALSE(v.parse(input));
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseCase
|
||||
{
|
||||
std::string_view testName;
|
||||
std::string_view base;
|
||||
bool shouldPass;
|
||||
};
|
||||
|
||||
std::string
|
||||
parseCaseName(::testing::TestParamInfo<ParseCase> const& info)
|
||||
{
|
||||
return std::string{info.param.testName};
|
||||
}
|
||||
|
||||
constexpr auto kParseCases = std::to_array<ParseCase>({
|
||||
{.testName = "zeroes", .base = "0.0.0", .shouldPass = true},
|
||||
{.testName = "simple", .base = "1.2.3", .shouldPass = true},
|
||||
{.testName = "max_int", .base = "2147483647.2147483647.2147483647", .shouldPass = true},
|
||||
|
||||
// negative values
|
||||
{.testName = "negative_major", .base = "-1.2.3", .shouldPass = false},
|
||||
{.testName = "negative_minor", .base = "1.-2.3", .shouldPass = false},
|
||||
{.testName = "negative_patch", .base = "1.2.-3", .shouldPass = false},
|
||||
|
||||
// missing parts
|
||||
{.testName = "empty", .base = "", .shouldPass = false},
|
||||
{.testName = "major_only", .base = "1", .shouldPass = false},
|
||||
{.testName = "major_then_dot", .base = "1.", .shouldPass = false},
|
||||
{.testName = "major_and_minor", .base = "1.2", .shouldPass = false},
|
||||
{.testName = "major_minor_then_dot", .base = "1.2.", .shouldPass = false},
|
||||
{.testName = "missing_major", .base = ".2.3", .shouldPass = false},
|
||||
|
||||
// whitespace
|
||||
{.testName = "leading_space", .base = " 1.2.3", .shouldPass = false},
|
||||
{.testName = "space_after_major", .base = "1 .2.3", .shouldPass = false},
|
||||
{.testName = "space_after_minor", .base = "1.2 .3", .shouldPass = false},
|
||||
{.testName = "trailing_space", .base = "1.2.3 ", .shouldPass = false},
|
||||
|
||||
// leading zeroes
|
||||
{.testName = "leading_zero_in_major", .base = "01.2.3", .shouldPass = false},
|
||||
{.testName = "leading_zero_in_minor", .base = "1.02.3", .shouldPass = false},
|
||||
{.testName = "leading_zero_in_patch", .base = "1.2.03", .shouldPass = false},
|
||||
});
|
||||
|
||||
struct ValuesCase
|
||||
{
|
||||
std::string_view testName;
|
||||
std::string_view input;
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
int patchVersion;
|
||||
IdentifierList preReleaseIdentifiers{}; // NOLINT(readability-redundant-member-init)
|
||||
IdentifierList metaData{}; // NOLINT(readability-redundant-member-init)
|
||||
};
|
||||
|
||||
std::string
|
||||
valuesCaseName(::testing::TestParamInfo<ValuesCase> const& info)
|
||||
{
|
||||
return std::string{info.param.testName};
|
||||
}
|
||||
|
||||
std::vector<ValuesCase> const kValuesCases{
|
||||
{
|
||||
.testName = "zero_major",
|
||||
.input = "0.1.2",
|
||||
.majorVersion = 0,
|
||||
.minorVersion = 1,
|
||||
.patchVersion = 2,
|
||||
},
|
||||
{
|
||||
.testName = "simple",
|
||||
.input = "1.2.3",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
},
|
||||
{
|
||||
.testName = "one_pre_release_identifier",
|
||||
.input = "1.2.3-rc1",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.preReleaseIdentifiers = {"rc1"},
|
||||
},
|
||||
{
|
||||
.testName = "two_pre_release_identifiers",
|
||||
.input = "1.2.3-rc1.debug",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.preReleaseIdentifiers = {"rc1", "debug"},
|
||||
},
|
||||
{
|
||||
.testName = "three_pre_release_identifiers",
|
||||
.input = "1.2.3-rc1.debug.asm",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.preReleaseIdentifiers = {"rc1", "debug", "asm"},
|
||||
},
|
||||
{
|
||||
.testName = "one_metadata_identifier",
|
||||
.input = "1.2.3+full",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.metaData = {"full"},
|
||||
},
|
||||
{
|
||||
.testName = "two_metadata_identifiers",
|
||||
.input = "1.2.3+full.prod",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.metaData = {"full", "prod"},
|
||||
},
|
||||
{
|
||||
.testName = "three_metadata_identifiers",
|
||||
.input = "1.2.3+full.prod.x86",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.metaData = {"full", "prod", "x86"},
|
||||
},
|
||||
{
|
||||
.testName = "pre_release_and_metadata",
|
||||
.input = "1.2.3-rc1.debug.asm+full.prod.x86",
|
||||
.majorVersion = 1,
|
||||
.minorVersion = 2,
|
||||
.patchVersion = 3,
|
||||
.preReleaseIdentifiers = {"rc1", "debug", "asm"},
|
||||
.metaData = {"full", "prod", "x86"},
|
||||
},
|
||||
};
|
||||
|
||||
struct OrderCase
|
||||
{
|
||||
std::string_view lesser;
|
||||
std::string_view greater;
|
||||
};
|
||||
|
||||
std::string
|
||||
orderCaseName(::testing::TestParamInfo<OrderCase> const& info)
|
||||
{
|
||||
return identifierFor(info.param.lesser) + "_below_" + identifierFor(info.param.greater);
|
||||
}
|
||||
|
||||
constexpr auto kOrderCases = std::to_array<OrderCase>({
|
||||
{.lesser = "1.0.0-alpha", .greater = "1.0.0-alpha.1"},
|
||||
{.lesser = "1.0.0-alpha.1", .greater = "1.0.0-alpha.beta"},
|
||||
{.lesser = "1.0.0-alpha.beta", .greater = "1.0.0-beta"},
|
||||
{.lesser = "1.0.0-beta", .greater = "1.0.0-beta.2"},
|
||||
{.lesser = "1.0.0-beta.2", .greater = "1.0.0-beta.11"},
|
||||
{.lesser = "1.0.0-beta.11", .greater = "1.0.0-rc.1"},
|
||||
{.lesser = "1.0.0-rc.1", .greater = "1.0.0"},
|
||||
{.lesser = "0.9.9", .greater = "1.0.0"},
|
||||
});
|
||||
|
||||
} // namespace
|
||||
|
||||
class SemanticVersionParse : public ::testing::TestWithParam<ParseCase>
|
||||
{
|
||||
};
|
||||
|
||||
// Exercises the base string on its own and with every combination of appended
|
||||
// pre-release identifiers and metadata.
|
||||
TEST_P(SemanticVersionParse, pre_release_and_metadata_combinations)
|
||||
{
|
||||
auto const& [testName, base, shouldPass] = GetParam();
|
||||
|
||||
for (auto const preRelease : kValidPreRelease)
|
||||
{
|
||||
for (auto const metaData : kValidMetaData)
|
||||
expectParse(base, preRelease, metaData, shouldPass);
|
||||
|
||||
for (auto const metaData : kInvalidMetaData)
|
||||
expectParse(base, preRelease, metaData, false);
|
||||
}
|
||||
|
||||
// A malformed pre-release section poisons the whole string, whatever
|
||||
// metadata follows it.
|
||||
for (auto const preRelease : kInvalidPreRelease)
|
||||
{
|
||||
for (auto const metaData : kValidMetaData)
|
||||
expectParse(base, preRelease, metaData, false);
|
||||
|
||||
for (auto const metaData : kInvalidMetaData)
|
||||
expectParse(base, preRelease, metaData, false);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Inputs,
|
||||
SemanticVersionParse,
|
||||
::testing::ValuesIn(kParseCases),
|
||||
parseCaseName);
|
||||
|
||||
class SemanticVersionValues : public ::testing::TestWithParam<ValuesCase>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(SemanticVersionValues, decomposes_into_components)
|
||||
{
|
||||
auto const& expected = GetParam();
|
||||
|
||||
SemanticVersion v;
|
||||
EXPECT_TRUE(v.parse(expected.input));
|
||||
|
||||
EXPECT_EQ(v.majorVersion, expected.majorVersion);
|
||||
EXPECT_EQ(v.minorVersion, expected.minorVersion);
|
||||
EXPECT_EQ(v.patchVersion, expected.patchVersion);
|
||||
|
||||
EXPECT_EQ(v.preReleaseIdentifiers, expected.preReleaseIdentifiers);
|
||||
EXPECT_EQ(v.metaData, expected.metaData);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Inputs,
|
||||
SemanticVersionValues,
|
||||
::testing::ValuesIn(kValuesCases),
|
||||
valuesCaseName);
|
||||
|
||||
class SemanticVersionOrder : public ::testing::TestWithParam<OrderCase>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(SemanticVersionOrder, lesser_precedes_greater)
|
||||
{
|
||||
auto const& [lesser, greater] = GetParam();
|
||||
|
||||
// Metadata takes no part in precedence, so attaching it to either side must
|
||||
// leave the ordering untouched.
|
||||
static constexpr auto kMetaData = std::to_array<std::string_view>({"", "+meta"});
|
||||
|
||||
for (auto const lesserMetaData : kMetaData)
|
||||
{
|
||||
for (auto const greaterMetaData : kMetaData)
|
||||
{
|
||||
auto const lesserInput = std::string{lesser}.append(lesserMetaData);
|
||||
auto const greaterInput = std::string{greater}.append(greaterMetaData);
|
||||
SCOPED_TRACE(
|
||||
::testing::Message() << '"' << lesserInput << "\" < \"" << greaterInput << '"');
|
||||
|
||||
SemanticVersion lesserVersion;
|
||||
SemanticVersion greaterVersion;
|
||||
EXPECT_TRUE(lesserVersion.parse(lesserInput));
|
||||
EXPECT_TRUE(greaterVersion.parse(greaterInput));
|
||||
|
||||
EXPECT_EQ(compare(lesserVersion, lesserVersion), 0);
|
||||
EXPECT_EQ(compare(greaterVersion, greaterVersion), 0);
|
||||
EXPECT_LT(compare(lesserVersion, greaterVersion), 0);
|
||||
EXPECT_GT(compare(greaterVersion, lesserVersion), 0);
|
||||
|
||||
EXPECT_LT(lesserVersion, greaterVersion);
|
||||
EXPECT_GT(greaterVersion, lesserVersion);
|
||||
EXPECT_EQ(lesserVersion, lesserVersion);
|
||||
EXPECT_EQ(greaterVersion, greaterVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Pairs,
|
||||
SemanticVersionOrder,
|
||||
::testing::ValuesIn(kOrderCases),
|
||||
orderCaseName);
|
||||
|
||||
} // namespace beast
|
||||
92
src/tests/libxrpl/beast/Zero.cpp
Normal file
92
src/tests/libxrpl/beast/Zero.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
struct AdlTester
|
||||
{
|
||||
};
|
||||
|
||||
int
|
||||
signum(AdlTester)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace inner_adl_test {
|
||||
|
||||
struct AdlTester2
|
||||
{
|
||||
};
|
||||
|
||||
int
|
||||
signum(AdlTester2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace inner_adl_test
|
||||
|
||||
namespace {
|
||||
|
||||
struct IntegerWrapper
|
||||
{
|
||||
int value;
|
||||
|
||||
IntegerWrapper(int v) : value(v)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] int
|
||||
signum() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testLhsZero(IntegerWrapper x)
|
||||
{
|
||||
EXPECT_EQ(x >= kZero, x.signum() >= 0);
|
||||
EXPECT_EQ(x > kZero, x.signum() > 0);
|
||||
EXPECT_EQ(x == kZero, x.signum() == 0);
|
||||
EXPECT_EQ(x != kZero, x.signum() != 0);
|
||||
EXPECT_EQ(x < kZero, x.signum() < 0);
|
||||
EXPECT_EQ(x <= kZero, x.signum() <= 0);
|
||||
}
|
||||
|
||||
void
|
||||
testRhsZero(IntegerWrapper x)
|
||||
{
|
||||
EXPECT_EQ(kZero >= x, 0 >= x.signum());
|
||||
EXPECT_EQ(kZero > x, 0 > x.signum());
|
||||
EXPECT_EQ(kZero == x, 0 == x.signum());
|
||||
EXPECT_EQ(kZero != x, 0 != x.signum());
|
||||
EXPECT_EQ(kZero < x, 0 < x.signum());
|
||||
EXPECT_EQ(kZero <= x, 0 <= x.signum());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(Zero, lhs)
|
||||
{
|
||||
testLhsZero(-7);
|
||||
testLhsZero(0);
|
||||
testLhsZero(32);
|
||||
}
|
||||
|
||||
TEST(Zero, rhs)
|
||||
{
|
||||
testRhsZero(-4);
|
||||
testRhsZero(0);
|
||||
testRhsZero(64);
|
||||
}
|
||||
|
||||
TEST(Zero, adl)
|
||||
{
|
||||
EXPECT_TRUE(AdlTester{} == kZero);
|
||||
EXPECT_TRUE(inner_adl_test::AdlTester2{} == kZero);
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
146
src/tests/libxrpl/nodestore/Codec.cpp
Normal file
146
src/tests/libxrpl/nodestore/Codec.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <xrpl/nodestore/detail/codec.h>
|
||||
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <nudb/detail/buffer.hpp>
|
||||
#include <nudb/detail/stream.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace xrpl;
|
||||
using namespace xrpl::node_store;
|
||||
|
||||
namespace {
|
||||
|
||||
// v1 inner-node layout: 16 hashes of 32 bytes each
|
||||
constexpr std::size_t kHashCount = 16;
|
||||
constexpr std::size_t kHashSize = 32;
|
||||
|
||||
std::vector<std::uint8_t>
|
||||
makeInnerNode(std::size_t nonEmptySlots)
|
||||
{
|
||||
using namespace nudb::detail;
|
||||
|
||||
static constexpr std::size_t kInnerNodeSize = 525;
|
||||
|
||||
std::array<std::uint8_t, kHashCount * kHashSize> hashes{};
|
||||
for (auto slot = 0uz; slot < nonEmptySlots; ++slot)
|
||||
{
|
||||
for (auto byte = 0uz; byte < kHashSize; ++byte)
|
||||
{
|
||||
std::size_t const offset = (slot * kHashSize) + byte;
|
||||
hashes[offset] = static_cast<std::uint8_t>((offset % 255) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> blob(kInnerNodeSize);
|
||||
ostream os(blob.data(), blob.size());
|
||||
write<std::uint32_t>(os, 0); // index
|
||||
write<std::uint32_t>(os, 0); // unused
|
||||
write<std::uint8_t>(os, static_cast<std::uint8_t>(NodeObjectType::Unknown));
|
||||
write<std::uint32_t>(os, static_cast<std::uint32_t>(HashPrefix::InnerNode));
|
||||
write(os, hashes.data(), hashes.size());
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
std::uint8_t
|
||||
codecType(std::pair<void const*, std::size_t> const& compressed)
|
||||
{
|
||||
return static_cast<std::uint8_t const*>(compressed.first)[0];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// All 16 hash slots populated - "full v1 inner node"
|
||||
TEST(Codec, inner_node_full_roundtrip)
|
||||
{
|
||||
static constexpr std::uint8_t kTypeInnerNodeFull = 3;
|
||||
|
||||
auto const blob = makeInnerNode(kHashCount);
|
||||
|
||||
nudb::detail::buffer compressBuf;
|
||||
auto const compressed = nodeobjectCompress(blob.data(), blob.size(), compressBuf);
|
||||
|
||||
EXPECT_EQ(codecType(compressed), kTypeInnerNodeFull);
|
||||
EXPECT_EQ(compressed.second, sizeVarint(kTypeInnerNodeFull) + (kHashCount * kHashSize));
|
||||
|
||||
nudb::detail::buffer decompressBuf;
|
||||
auto const restored = nodeobjectDecompress(compressed.first, compressed.second, decompressBuf);
|
||||
|
||||
EXPECT_EQ(restored.second, blob.size());
|
||||
EXPECT_EQ(std::memcmp(restored.first, blob.data(), blob.size()), 0);
|
||||
}
|
||||
|
||||
// Some hash slots empty - "compressed v1 inner node"
|
||||
TEST(Codec, inner_node_compressed_roundtrip)
|
||||
{
|
||||
static constexpr std::uint8_t kTypeInnerNodeCompressed = 2;
|
||||
static constexpr std::size_t kNonEmpty = 5;
|
||||
auto const blob = makeInnerNode(kNonEmpty);
|
||||
|
||||
nudb::detail::buffer compressBuf;
|
||||
auto const compressed = nodeobjectCompress(blob.data(), blob.size(), compressBuf);
|
||||
|
||||
EXPECT_EQ(codecType(compressed), kTypeInnerNodeCompressed);
|
||||
EXPECT_EQ(
|
||||
compressed.second,
|
||||
sizeVarint(kTypeInnerNodeCompressed) + sizeof(std::uint16_t) + (kNonEmpty * kHashSize));
|
||||
EXPECT_LT(compressed.second, blob.size());
|
||||
|
||||
nudb::detail::buffer decompressBuf;
|
||||
auto const restored = nodeobjectDecompress(compressed.first, compressed.second, decompressBuf);
|
||||
|
||||
EXPECT_EQ(restored.second, blob.size());
|
||||
EXPECT_EQ(std::memcmp(restored.first, blob.data(), blob.size()), 0);
|
||||
}
|
||||
|
||||
// Anything that is not a v1 inner node - lz4 compressed
|
||||
TEST(Codec, lz4_roundtrip)
|
||||
{
|
||||
// A payload that is deliberately not a v1 inner node (any size other than 525), filled with a
|
||||
// short repeating pattern so lz4 actually shrinks it.
|
||||
static constexpr std::size_t kNonInnerNodeSize = 1000;
|
||||
static constexpr std::size_t kBytePatternPeriod = 7;
|
||||
static constexpr std::uint8_t kTypeLz4 = 1;
|
||||
|
||||
std::vector<std::uint8_t> blob(kNonInnerNodeSize);
|
||||
for (auto i = 0uz; i < blob.size(); ++i)
|
||||
blob[i] = static_cast<std::uint8_t>(i % kBytePatternPeriod);
|
||||
|
||||
nudb::detail::buffer compressBuf;
|
||||
auto const compressed = nodeobjectCompress(blob.data(), blob.size(), compressBuf);
|
||||
|
||||
EXPECT_EQ(codecType(compressed), kTypeLz4);
|
||||
|
||||
nudb::detail::buffer decompressBuf;
|
||||
auto const restored = nodeobjectDecompress(compressed.first, compressed.second, decompressBuf);
|
||||
|
||||
EXPECT_EQ(restored.second, blob.size());
|
||||
EXPECT_EQ(std::memcmp(restored.first, blob.data(), blob.size()), 0);
|
||||
}
|
||||
|
||||
// An uncompressed blob is never produced by the compressor but must still decode: leading varint 0
|
||||
// followed by the raw payload.
|
||||
TEST(Codec, uncompressed_passthrough)
|
||||
{
|
||||
static constexpr std::uint8_t kTypeUncompressed = 0;
|
||||
static constexpr auto payload = std::to_array<std::uint8_t>({0xde, 0xad, 0xbe, 0xef, 0x2a});
|
||||
|
||||
std::vector<std::uint8_t> blob;
|
||||
blob.push_back(kTypeUncompressed); // leading varint type tag
|
||||
blob.insert(blob.end(), payload.begin(), payload.end());
|
||||
|
||||
nudb::detail::buffer decompressBuf;
|
||||
auto const restored = nodeobjectDecompress(blob.data(), blob.size(), decompressBuf);
|
||||
|
||||
EXPECT_EQ(restored.second, payload.size());
|
||||
EXPECT_EQ(std::memcmp(restored.first, payload.data(), payload.size()), 0);
|
||||
}
|
||||
46
src/tests/libxrpl/nodestore/Varint.cpp
Normal file
46
src/tests/libxrpl/nodestore/Varint.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <xrpl/nodestore/detail/Varint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
using namespace xrpl::node_store;
|
||||
|
||||
TEST(Varint, encode_decode)
|
||||
{
|
||||
static constexpr auto kValues = std::to_array<std::size_t>({
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
126,
|
||||
127,
|
||||
128,
|
||||
253,
|
||||
254,
|
||||
255,
|
||||
16127,
|
||||
16128,
|
||||
16129,
|
||||
0xff,
|
||||
0xffff,
|
||||
0xffffffff,
|
||||
0xffffffffffffUL,
|
||||
std::numeric_limits<std::size_t>::max(),
|
||||
});
|
||||
|
||||
for (auto const value : kValues)
|
||||
{
|
||||
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> buffer{};
|
||||
auto const bytesWritten = writeVarint(buffer.data(), value);
|
||||
EXPECT_GT(bytesWritten, 0u);
|
||||
EXPECT_EQ(bytesWritten, sizeVarint(value));
|
||||
|
||||
std::size_t decoded = 0;
|
||||
auto const bytesRead = readVarint(buffer.data(), bytesWritten, decoded);
|
||||
EXPECT_EQ(bytesRead, bytesWritten);
|
||||
EXPECT_EQ(value, decoded);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include <xrpl/nodestore/detail/varint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace xrpl::node_store;
|
||||
|
||||
TEST(varint, encode_decode)
|
||||
{
|
||||
std::vector<std::size_t> const kVALUES = {
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
126,
|
||||
127,
|
||||
128,
|
||||
253,
|
||||
254,
|
||||
255,
|
||||
16127,
|
||||
16128,
|
||||
16129,
|
||||
0xff,
|
||||
0xffff,
|
||||
0xffffffff,
|
||||
0xffffffffffffUL,
|
||||
0xffffffffffffffffUL};
|
||||
|
||||
for (auto const v : kVALUES)
|
||||
{
|
||||
SCOPED_TRACE("value=" + std::to_string(v));
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
auto const n0 = writeVarint(vi.data(), v);
|
||||
EXPECT_GT(n0, 0u) << "write error";
|
||||
EXPECT_EQ(n0, sizeVarint(v)) << "size error";
|
||||
std::size_t v1 = 0;
|
||||
auto const n1 = readVarint(vi.data(), n0, v1);
|
||||
EXPECT_EQ(n1, n0) << "read error";
|
||||
EXPECT_EQ(v1, v) << "wrong value";
|
||||
}
|
||||
}
|
||||
26
src/tests/libxrpl/protocol/ApiVersion.cpp
Normal file
26
src/tests/libxrpl/protocol/ApiVersion.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <xrpl/protocol/ApiVersion.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace xrpl;
|
||||
|
||||
TEST(ApiVersion, invariants)
|
||||
{
|
||||
static_assert(RPC::kApiMinimumSupportedVersion <= RPC::kApiMaximumSupportedVersion);
|
||||
static_assert(RPC::kApiMinimumSupportedVersion <= RPC::kApiMaximumValidVersion);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion <= RPC::kApiMaximumValidVersion);
|
||||
static_assert(RPC::kApiBetaVersion <= RPC::kApiMaximumValidVersion);
|
||||
}
|
||||
|
||||
// Update when we change versions
|
||||
TEST(ApiVersion, versions)
|
||||
{
|
||||
static_assert(RPC::kApiMinimumSupportedVersion >= 1);
|
||||
static_assert(RPC::kApiMinimumSupportedVersion < 2);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion >= 2);
|
||||
static_assert(RPC::kApiMaximumSupportedVersion < 3);
|
||||
static_assert(RPC::kApiMaximumValidVersion >= 3);
|
||||
static_assert(RPC::kApiMaximumValidVersion < 4);
|
||||
static_assert(RPC::kApiBetaVersion >= 3);
|
||||
static_assert(RPC::kApiBetaVersion < 4);
|
||||
}
|
||||
49
src/tests/libxrpl/protocol/Serializer.cpp
Normal file
49
src/tests/libxrpl/protocol/Serializer.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
using namespace xrpl;
|
||||
|
||||
TEST(Serializer, add32_roundtrip)
|
||||
{
|
||||
static constexpr auto kValues = std::to_array<std::int32_t>({
|
||||
std::numeric_limits<std::int32_t>::min(),
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
std::numeric_limits<std::int32_t>::max(),
|
||||
});
|
||||
|
||||
for (std::int32_t const value : kValues)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(value);
|
||||
EXPECT_EQ(s.size(), 4);
|
||||
SerialIter sit(s.slice());
|
||||
EXPECT_EQ(sit.geti32(), value);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Serializer, add64_roundtrip)
|
||||
{
|
||||
static constexpr auto kValues = std::to_array<std::int64_t>({
|
||||
std::numeric_limits<std::int64_t>::min(),
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
std::numeric_limits<std::int64_t>::max(),
|
||||
});
|
||||
|
||||
for (std::int64_t const value : kValues)
|
||||
{
|
||||
Serializer s;
|
||||
s.add64(value);
|
||||
EXPECT_EQ(s.size(), 8);
|
||||
SerialIter sit(s.slice());
|
||||
EXPECT_EQ(sit.geti64(), value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user