mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-30 18:40:28 +00:00
Merge branch 'pratik/otel-phase3-tx-tracing' into pratik/otel-phase4-consensus-tracing
This commit is contained in:
@@ -27,15 +27,17 @@ target_link_libraries(xrpl_tests PRIVATE GTest::gtest GTest::gmock xrpl.libxrpl)
|
||||
# supported on Windows.
|
||||
set(test_modules
|
||||
basics
|
||||
beast
|
||||
consensus
|
||||
crypto
|
||||
json
|
||||
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