mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-10 16:50:28 +00:00
Compare commits
2 Commits
ximinez/31
...
bthomee/ig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
599a651e9e | ||
|
|
dd425ffc6b |
@@ -159,7 +159,6 @@ test.peerfinder > xrpl.protocol
|
||||
test.protocol > test.jtx
|
||||
test.protocol > test.unit_test
|
||||
test.protocol > xrpl.basics
|
||||
test.protocol > xrpld.core
|
||||
test.protocol > xrpl.json
|
||||
test.protocol > xrpl.protocol
|
||||
test.rpc > test.jtx
|
||||
|
||||
1
.github/workflows/conflicting-pr.yml
vendored
1
.github/workflows/conflicting-pr.yml
vendored
@@ -14,6 +14,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'IgnoreConflicts') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if PRs are dirty
|
||||
|
||||
@@ -305,9 +305,7 @@ public:
|
||||
XRPL_ASSERT(
|
||||
c.size() * sizeof(typename Container::value_type) == size(),
|
||||
"xrpl::BaseUInt::fromRaw(Container auto) : input size match");
|
||||
std::size_t const canCopy =
|
||||
std::min(size(), c.size() * sizeof(typename Container::value_type));
|
||||
std::memcpy(result.data_.data(), c.data(), canCopy);
|
||||
std::memcpy(result.data_.data(), c.data(), size());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -321,11 +319,7 @@ public:
|
||||
XRPL_ASSERT(
|
||||
c.size() * sizeof(typename Container::value_type) == size(),
|
||||
"xrpl::BaseUInt::operator=(Container auto) : input size match");
|
||||
std::size_t const canCopy =
|
||||
std::min(size(), c.size() * sizeof(typename Container::value_type));
|
||||
if (canCopy < size())
|
||||
*this = beast::kZero;
|
||||
std::memcpy(data_.data(), c.data(), canCopy);
|
||||
std::memcpy(data_.data(), c.data(), size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
@@ -865,101 +863,6 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
testIssueFromJson()
|
||||
{
|
||||
testcase("issueFromJson");
|
||||
|
||||
// Valid XRP — no issuer field
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "XRP";
|
||||
auto const issue = issueFromJson(jv);
|
||||
BEAST_EXPECT(isXRP(issue));
|
||||
}
|
||||
|
||||
// Valid IOU — legitimate issuer
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
|
||||
auto const issue = issueFromJson(jv);
|
||||
BEAST_EXPECT(!isXRP(issue));
|
||||
BEAST_EXPECT(issue.account != noAccount());
|
||||
}
|
||||
|
||||
// noAccount() is the MPT sentinel in binary serialization - must be
|
||||
// rejected
|
||||
try
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = to_string(noAccount());
|
||||
issueFromJson(jv);
|
||||
fail("noAccount() accepted as IOU issuer");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
// xrpAccount() is the XRP sentinel (all zeros) - must be rejected
|
||||
// as IOU issuer
|
||||
try
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = to_string(xrpAccount());
|
||||
issueFromJson(jv);
|
||||
fail("xrpAccount() accepted as IOU issuer");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
// Invalid base58 — must be rejected
|
||||
try
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = "not_a_valid_address";
|
||||
issueFromJson(jv);
|
||||
fail("invalid base58 accepted as IOU issuer");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
// Non-XRP currency with no issuer field — must be rejected
|
||||
try
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
issueFromJson(jv);
|
||||
fail("missing issuer accepted");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
// XRP with an issuer field — must be rejected
|
||||
try
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "XRP";
|
||||
jv[jss::issuer] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
|
||||
issueFromJson(jv);
|
||||
fail("XRP with issuer accepted");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -994,9 +897,6 @@ public:
|
||||
// ---
|
||||
testIssueDomainSets();
|
||||
testIssueDomainMaps();
|
||||
|
||||
// ---
|
||||
testIssueFromJson();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
|
||||
#include <test/jtx/Account.h>
|
||||
#include <test/jtx/Env.h>
|
||||
#include <test/jtx/amount.h> // IWYU pragma: keep
|
||||
#include <test/jtx/envconfig.h>
|
||||
|
||||
#include <xrpld/core/Config.h>
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/json/to_string.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STIssue.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
@@ -146,143 +137,12 @@ public:
|
||||
"000000000000000000000000000000000000000000000002");
|
||||
}
|
||||
|
||||
void
|
||||
testNoAccountIssuerRpc()
|
||||
{
|
||||
testcase("noAccount issuer rejected via RPC sign");
|
||||
|
||||
using namespace jtx;
|
||||
Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
|
||||
cfg->loadFromString("[signing_support]\ntrue");
|
||||
return cfg;
|
||||
})};
|
||||
|
||||
Account const alice{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
env.close();
|
||||
|
||||
json::Value txJson;
|
||||
txJson[jss::TransactionType] = "AMMDelete";
|
||||
txJson[jss::Account] = alice.human();
|
||||
txJson[jss::Asset][jss::currency] = "USD";
|
||||
txJson[jss::Asset][jss::issuer] = to_string(noAccount());
|
||||
txJson[jss::Asset2][jss::currency] = "XRP";
|
||||
|
||||
json::Value req;
|
||||
req[jss::tx_json] = txJson;
|
||||
req[jss::secret] = alice.name();
|
||||
|
||||
auto const result = env.rpc("json", "sign", to_string(req))[jss::result];
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Field 'tx_json.Asset' has invalid data.");
|
||||
}
|
||||
|
||||
void
|
||||
testNoAccountIssuer()
|
||||
{
|
||||
testcase("noAccount issuer rejection");
|
||||
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = to_string(noAccount());
|
||||
|
||||
try
|
||||
{
|
||||
issueFromJson(sfAsset, jv);
|
||||
fail("issueFromJson accepted noAccount() as IOU issuer");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Serializer s;
|
||||
s.addBitString(toCurrency("USD"));
|
||||
s.addBitString(noAccount());
|
||||
SerialIter iter(s.slice());
|
||||
|
||||
try
|
||||
{
|
||||
STIssue const stissue(iter, sfAsset);
|
||||
fail(
|
||||
"STIssue deserialization of [USD][noAccount()] should "
|
||||
"throw");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testXrpAccountIssuerRpc()
|
||||
{
|
||||
testcase("xrpAccount issuer rejected via RPC sign");
|
||||
|
||||
using namespace jtx;
|
||||
Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
|
||||
cfg->loadFromString("[signing_support]\ntrue");
|
||||
return cfg;
|
||||
})};
|
||||
|
||||
Account const alice{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
env.close();
|
||||
|
||||
json::Value txJson;
|
||||
txJson[jss::TransactionType] = "AMMDelete";
|
||||
txJson[jss::Account] = alice.human();
|
||||
txJson[jss::Asset][jss::currency] = "USD";
|
||||
txJson[jss::Asset][jss::issuer] = to_string(xrpAccount());
|
||||
txJson[jss::Asset2][jss::currency] = "XRP";
|
||||
|
||||
json::Value req;
|
||||
req[jss::tx_json] = txJson;
|
||||
req[jss::secret] = alice.name();
|
||||
|
||||
auto const result = env.rpc("json", "sign", to_string(req))[jss::result];
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Field 'tx_json.Asset' has invalid data.");
|
||||
}
|
||||
|
||||
void
|
||||
testXrpAccountIssuer()
|
||||
{
|
||||
testcase("xrpAccount issuer rejection");
|
||||
|
||||
{
|
||||
json::Value jv;
|
||||
jv[jss::currency] = "USD";
|
||||
jv[jss::issuer] = to_string(xrpAccount());
|
||||
|
||||
try
|
||||
{
|
||||
issueFromJson(sfAsset, jv);
|
||||
fail("issueFromJson accepted xrpAccount() as IOU issuer");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
// compliments other unit tests to ensure complete coverage
|
||||
testConstructor();
|
||||
testCompare();
|
||||
testNoAccountIssuerRpc();
|
||||
testNoAccountIssuer();
|
||||
testXrpAccountIssuerRpc();
|
||||
testXrpAccountIssuer();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/Seed.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/protocol/nft.h>
|
||||
@@ -33,7 +32,6 @@
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::test {
|
||||
@@ -1352,86 +1350,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testAccountObjectDoesntShowCancelledOffers()
|
||||
{
|
||||
testcase("AccountObjectDoesntShowCancelledOffers");
|
||||
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
|
||||
Account const alice{"alice"};
|
||||
Account const bob{"bob"};
|
||||
auto const eur = bob["EUR"];
|
||||
env.fund(XRP(10000), alice, bob);
|
||||
env.close();
|
||||
|
||||
auto const rpcAccountObjects = [&](std::optional<uint32_t> limit = std::nullopt) {
|
||||
json::Value params;
|
||||
params[jss::account] = alice.human();
|
||||
if (limit.has_value())
|
||||
{
|
||||
params[jss::limit] = *limit;
|
||||
}
|
||||
return env.rpc("json", "account_objects", to_string(params));
|
||||
};
|
||||
|
||||
auto const numEntries = 33;
|
||||
std::vector<uint32_t> seqs;
|
||||
seqs.reserve(numEntries);
|
||||
for ([[maybe_unused]] auto _ : std::ranges::iota_view{0, numEntries})
|
||||
{
|
||||
json::Value params;
|
||||
params[jss::secret] = toBase58(generateSeed("alice"));
|
||||
params[jss::tx_json] = offer(alice, eur(1), XRP(2));
|
||||
auto const res = env.rpc("json", "submit", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(res[jss::engine_result].asString() == "tesSUCCESS");
|
||||
seqs.push_back(env.seq(alice));
|
||||
}
|
||||
|
||||
auto res = rpcAccountObjects();
|
||||
BEAST_EXPECT(res[jss::result][jss::account_objects].size() == numEntries);
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::limit));
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::marker));
|
||||
|
||||
for (auto const s : std::views::all(seqs) | std::views::take(numEntries - 1))
|
||||
{
|
||||
json::Value params;
|
||||
params[jss::secret] = toBase58(generateSeed("alice"));
|
||||
params[jss::tx_json] = offerCancel(alice, s - 1);
|
||||
auto const res = env.rpc("json", "submit", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(res[jss::engine_result].asString() == "tesSUCCESS");
|
||||
}
|
||||
|
||||
res = rpcAccountObjects();
|
||||
BEAST_EXPECT(res[jss::result][jss::account_objects].size() == 1);
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::limit));
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::marker));
|
||||
|
||||
{
|
||||
json::Value params;
|
||||
params[jss::secret] = toBase58(generateSeed("alice"));
|
||||
json::Value txJson;
|
||||
txJson[jss::TransactionType] = jss::NFTokenMint;
|
||||
txJson[jss::Account] = to_string(alice.id());
|
||||
txJson["NFTokenTaxon"] = 1;
|
||||
params[jss::tx_json] = txJson;
|
||||
auto const res = env.rpc("json", "submit", to_string(params))[jss::result];
|
||||
BEAST_EXPECT(res[jss::engine_result].asString() == "tesSUCCESS");
|
||||
}
|
||||
env.close();
|
||||
|
||||
res = rpcAccountObjects();
|
||||
BEAST_EXPECT(res[jss::result][jss::account_objects].size() == 2);
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::limit));
|
||||
BEAST_EXPECT(not res[jss::result].isMember(jss::marker));
|
||||
|
||||
res = rpcAccountObjects(1);
|
||||
BEAST_EXPECT(res[jss::result][jss::account_objects].size() == 1);
|
||||
BEAST_EXPECT(res[jss::result][jss::limit].asUInt() == 1);
|
||||
BEAST_EXPECT(res[jss::result].isMember(jss::marker));
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -1442,7 +1360,6 @@ public:
|
||||
testNFTsMarker();
|
||||
testAccountNFTs();
|
||||
testAccountObjectMarker();
|
||||
testAccountObjectDoesntShowCancelledOffers();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <test/jtx/Env.h>
|
||||
#include <test/jtx/amount.h>
|
||||
#include <test/jtx/envconfig.h>
|
||||
#include <test/jtx/multisign.h>
|
||||
#include <test/jtx/noop.h>
|
||||
#include <test/jtx/pay.h>
|
||||
#include <test/jtx/seq.h>
|
||||
@@ -881,125 +880,6 @@ class Transaction_test : public beast::unit_test::Suite
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testSignForNetworkIDValidation()
|
||||
{
|
||||
testcase("SignFor NetworkID validation");
|
||||
using namespace test::jtx;
|
||||
|
||||
Account const owner{"owner"};
|
||||
Account const signer{"signer"};
|
||||
|
||||
auto makeConfig = [](std::uint32_t networkID) {
|
||||
return envconfig([networkID](std::unique_ptr<Config> cfg) {
|
||||
cfg->networkId = networkID;
|
||||
return cfg;
|
||||
});
|
||||
};
|
||||
|
||||
auto setupEnv = [&](Env& env) {
|
||||
env.fund(XRP(10'000), owner, signer);
|
||||
env.close();
|
||||
env(signers(owner, 1, {{signer, 1}}));
|
||||
env.close();
|
||||
};
|
||||
|
||||
auto makeTx = [&](Env& env) {
|
||||
json::Value tx;
|
||||
tx[jss::TransactionType] = jss::AccountSet;
|
||||
tx[jss::Account] = owner.human();
|
||||
tx[jss::Sequence] = env.seq(owner);
|
||||
tx[jss::Fee] = "100";
|
||||
tx[jss::SigningPubKey] = "";
|
||||
return tx;
|
||||
};
|
||||
|
||||
auto signFor = [&](Env& env, json::Value const& tx) {
|
||||
json::Value signReq;
|
||||
signReq[jss::tx_json] = tx;
|
||||
signReq[jss::account] = signer.human();
|
||||
signReq[jss::secret] = signer.name();
|
||||
return env.rpc("json", "sign_for", to_string(signReq))[jss::result];
|
||||
};
|
||||
|
||||
// Test case: NetworkID < 1024 - field is not required
|
||||
{
|
||||
Env env{*this, makeConfig(500)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::status] == "success");
|
||||
BEAST_EXPECT(!result[jss::tx_json].isMember(jss::NetworkID));
|
||||
}
|
||||
|
||||
// Test case: NetworkID > 1024 - missing NetworkID field
|
||||
{
|
||||
Env env{*this, makeConfig(2040)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Missing field 'tx_json.NetworkID'.");
|
||||
}
|
||||
|
||||
// Test case: NetworkID > 1024 - NetworkID field is not a number
|
||||
{
|
||||
Env env{*this, makeConfig(2040)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
tx[jss::NetworkID] = "not_a_number";
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Invalid field 'tx_json.NetworkID'.");
|
||||
}
|
||||
|
||||
// Test case: NetworkID > 1024 - NetworkID field is not integral
|
||||
{
|
||||
Env env{*this, makeConfig(2040)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
tx[jss::NetworkID] = 2040.1;
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Invalid field 'tx_json.NetworkID'.");
|
||||
}
|
||||
|
||||
// Test case: NetworkID > 1024 - NetworkID field is different from
|
||||
// actual NetworkID
|
||||
{
|
||||
Env env{*this, makeConfig(2040)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
tx[jss::NetworkID] = 9999;
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::error] == "invalidParams");
|
||||
BEAST_EXPECT(result[jss::error_message] == "Invalid field 'tx_json.NetworkID'.");
|
||||
}
|
||||
|
||||
// Test case: NetworkID > 1024 - NetworkID field is correct
|
||||
{
|
||||
Env env{*this, makeConfig(2040)};
|
||||
setupEnv(env);
|
||||
|
||||
auto tx = makeTx(env);
|
||||
tx[jss::NetworkID] = 2040;
|
||||
auto result = signFor(env, tx);
|
||||
|
||||
BEAST_EXPECT(result[jss::status] == "success");
|
||||
BEAST_EXPECT(result[jss::tx_json][jss::NetworkID].asUInt() == 2040);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
@@ -1009,8 +889,6 @@ public:
|
||||
|
||||
FeatureBitset const all{testableAmendments()};
|
||||
testWithFeats(all);
|
||||
|
||||
testSignForNetworkIDValidation();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -122,73 +122,6 @@ struct BaseUintTest : public ::testing::Test
|
||||
}
|
||||
};
|
||||
|
||||
using BaseUintDeathTest = BaseUintTest;
|
||||
|
||||
TEST_F(BaseUintDeathTest, fromRaw_size_mismatch)
|
||||
{
|
||||
// ENABLE_VOIDSTAR is a debug build, but does not crash on failed asserts. Rather than twist
|
||||
// these tests into knots to make them work, just skip them.
|
||||
#ifdef ENABLE_VOIDSTAR
|
||||
GTEST_SKIP() << "ENABLE_VOIDSTAR is a debug build, but does not crash on failed asserts.";
|
||||
#else
|
||||
auto smallConstruct = [] {
|
||||
// Container smaller than the base_uint (8 bytes vs 12 bytes for
|
||||
// test96). Only the first 8 bytes are copied; the remaining 4 bytes
|
||||
// stay zero.
|
||||
Blob const tooSmall{1, 2, 3, 4, 5, 6, 7, 8};
|
||||
BaseUInt96 const result = BaseUInt96::fromRaw(tooSmall);
|
||||
auto const resultText = to_string(result);
|
||||
EXPECT_EQ(resultText, "010203040506070800000000") << resultText;
|
||||
};
|
||||
EXPECT_DEBUG_DEATH(smallConstruct(), "input size match");
|
||||
|
||||
auto largeConstruct = [] {
|
||||
// Container larger than the base_uint (16 bytes vs 12 bytes for
|
||||
// test96). Only the first 12 bytes are copied; the extra bytes are
|
||||
// ignored.
|
||||
Blob const tooBig{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
BaseUInt96 const result = BaseUInt96::fromRaw(tooBig);
|
||||
auto const resultText = to_string(result);
|
||||
EXPECT_EQ(resultText, "0102030405060708090A0B0C") << resultText;
|
||||
};
|
||||
EXPECT_DEBUG_DEATH(largeConstruct(), "input size match");
|
||||
|
||||
auto smallCopy = [] {
|
||||
// Container smaller than the base_uint (8 bytes vs 12 bytes for
|
||||
// test96). Only the first 8 bytes are copied; the remaining 4 bytes
|
||||
// stay zero.
|
||||
Blob const tooSmall{1, 2, 3, 4, 5, 6, 7, 8};
|
||||
BaseUInt96 result{};
|
||||
--result;
|
||||
{
|
||||
auto const originalText = to_string(result);
|
||||
EXPECT_EQ(originalText, "FFFFFFFFFFFFFFFFFFFFFFFF") << originalText;
|
||||
}
|
||||
result = tooSmall;
|
||||
auto const resultText = to_string(result);
|
||||
EXPECT_EQ(resultText, "010203040506070800000000") << resultText;
|
||||
};
|
||||
EXPECT_DEBUG_DEATH(smallCopy(), "input size match");
|
||||
|
||||
auto const largeCopy = [] {
|
||||
// Container larger than the base_uint (16 bytes vs 12 bytes for
|
||||
// test96). Only the first 12 bytes are copied; the extra bytes are
|
||||
// ignored.
|
||||
Blob const tooBig{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
BaseUInt96 result{};
|
||||
--result;
|
||||
{
|
||||
auto const originalText = to_string(result);
|
||||
EXPECT_EQ(originalText, "FFFFFFFFFFFFFFFFFFFFFFFF") << originalText;
|
||||
}
|
||||
result = tooBig;
|
||||
auto const resultText = to_string(result);
|
||||
EXPECT_EQ(resultText, "0102030405060708090A0B0C") << resultText;
|
||||
};
|
||||
EXPECT_DEBUG_DEATH(largeCopy(), "input size match");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(BaseUintTest, base_uint)
|
||||
{
|
||||
static_assert(!std::is_constructible_v<BaseUInt96, std::complex<double>>);
|
||||
@@ -265,19 +198,6 @@ TEST_F(BaseUintTest, base_uint)
|
||||
EXPECT_EQ(d, 0);
|
||||
}
|
||||
|
||||
{
|
||||
// There are several ways to create a zero. beast::kZero is tested above. Test some
|
||||
// others.
|
||||
BaseUInt96 const z1;
|
||||
EXPECT_EQ(z1, z) << to_string(z1);
|
||||
|
||||
BaseUInt96 const z2{};
|
||||
EXPECT_EQ(z2, z) << to_string(z2);
|
||||
|
||||
BaseUInt96 const z3{0u};
|
||||
EXPECT_EQ(z3, z) << to_string(z3);
|
||||
}
|
||||
|
||||
BaseUInt96 n{z};
|
||||
n++;
|
||||
EXPECT_EQ(n, BaseUInt96(1));
|
||||
|
||||
Reference in New Issue
Block a user