Skip to content

Commit 92f99fb

Browse files
committed
Add basic functionality tests
1 parent 8e57296 commit 92f99fb

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

src/util/test/XDRCerealTests.cpp

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
#include "crypto/StrKey.h"
12
#include "test/Catch2.h"
23
#include "util/Decoder.h"
4+
#include <fmt/format.h>
35
#include <xdrpp/autocheck.h>
46

57
namespace
@@ -84,6 +86,7 @@ roundtripRandoms()
8486
ROUNDTRIP(bool)
8587
ROUNDTRIP(xdr::pointer<xdr::pointer<int>>)
8688

89+
#ifdef TEST_XDR_ROUNDTRIPS
8790
ROUNDTRIP(AccountEntry)
8891
ROUNDTRIP(AccountEntryExtensionV1)
8992
ROUNDTRIP(AccountEntryExtensionV2)
@@ -422,4 +425,260 @@ ROUNDTRIP(UInt128Parts)
422425
ROUNDTRIP(UInt256Parts)
423426
ROUNDTRIP(UpgradeEntryMeta)
424427
ROUNDTRIP(UpgradeType)
428+
#endif
429+
430+
template <typename T>
431+
std::string
432+
toCerealCompact(T const& t, std::string const& name)
433+
{
434+
using stellar::xdrToCerealString;
435+
using namespace rapidjson;
436+
std::string result = xdrToCerealString(t, name);
437+
Document d;
438+
d.Parse(result.c_str());
439+
440+
StringBuffer sb;
441+
Writer<StringBuffer> w(sb);
442+
d.Accept(w);
443+
444+
return sb.GetString();
445+
}
446+
447+
template <uint32_t N>
448+
void
449+
copyHexToArray(xdr::opaque_array<N>& arr, char const* hex)
450+
{
451+
auto bin = stellar::hexToBin(hex);
452+
releaseAssert(bin.size() <= N);
453+
std::copy(bin.begin(), bin.end(), arr.begin());
454+
}
455+
456+
template <uint32_t N>
457+
void
458+
copyToArray(xdr::opaque_array<N>& arr, std::string const& s)
459+
{
460+
releaseAssert(s.size() <= N);
461+
std::copy(s.begin(), s.end(), arr.begin());
462+
}
463+
464+
TEST_CASE("XDRCereal overrides")
465+
{
466+
using namespace stellar;
467+
char const accountIdHex[] =
468+
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
469+
static_assert(sizeof(accountIdHex) ==
470+
uint256::container_fixed_nelem * 2 + 1);
471+
static_assert(std::is_same_v<uint256, Hash>);
472+
473+
// Check xstring
474+
{
475+
REQUIRE(toCerealCompact(xdr::xstring<5>{"abc"}, "s") ==
476+
R"({"s":"abc"})");
477+
xdr::xstring<5> s{std::string{'a', '\0', 'b', 'c'}};
478+
REQUIRE(toCerealCompact(s, "s") == R"({"s":{"raw":"61006263"}})");
479+
}
480+
481+
// Check opaque array
482+
{
483+
xdr::opaque_array<8> o;
484+
copyHexToArray(o, "0123456789abcdef");
485+
REQUIRE(toCerealCompact(o, "o") == R"({"o":"0123456789abcdef"})");
486+
}
487+
488+
// Check container (xdr::xvector)
489+
{
490+
xdr::xvector<uint32_t> v{1, 2, 3};
491+
CHECK(toCerealCompact(v, "v") == R"({"v":[1,2,3]})");
492+
}
493+
494+
// Check container with nested override (xdr::xvector of enums)
495+
{
496+
xdr::xvector<Asset> v;
497+
Asset a;
498+
a.type(ASSET_TYPE_NATIVE);
499+
v.push_back(a);
500+
a.type(ASSET_TYPE_CREDIT_ALPHANUM4);
501+
copyToArray(a.alphaNum4().assetCode, "USD");
502+
copyHexToArray(a.alphaNum4().issuer.ed25519(), accountIdHex);
503+
v.push_back(a);
504+
CHECK(
505+
toCerealCompact(v, "v") ==
506+
R"({"v":["NATIVE",{"assetCode":"USD","issuer":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"}]})");
507+
}
508+
509+
// Check opaque_vec
510+
{
511+
xdr::opaque_vec<> v{0x01, 0x23, 0x45};
512+
CHECK(toCerealCompact(v, "v") == R"({"v":"012345"})");
513+
}
514+
515+
// Check PublicKey
516+
{
517+
PublicKey pk;
518+
pk.type(PUBLIC_KEY_TYPE_ED25519);
519+
copyHexToArray(pk.ed25519(), accountIdHex);
520+
CHECK(
521+
toCerealCompact(pk, "pk") ==
522+
R"({"pk":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"})");
523+
}
524+
525+
// Check SCAddress (account)
526+
{
527+
SCAddress addr;
528+
addr.type(SC_ADDRESS_TYPE_ACCOUNT);
529+
addr.accountId().type(PUBLIC_KEY_TYPE_ED25519);
530+
copyHexToArray(addr.accountId().ed25519(), accountIdHex);
531+
CHECK(
532+
toCerealCompact(addr, "a") ==
533+
R"({"a":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"})");
534+
}
535+
536+
// Check SCAddress (contract)
537+
{
538+
SCAddress addr;
539+
addr.type(SC_ADDRESS_TYPE_CONTRACT);
540+
copyHexToArray(addr.contractId(), accountIdHex);
541+
CHECK(
542+
toCerealCompact(addr, "a") ==
543+
R"({"a":"CAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG67KRS"})");
544+
}
545+
546+
// Check ConfigUpgradeSetKey
547+
{
548+
ConfigUpgradeSetKey key;
549+
copyHexToArray(key.contentHash, accountIdHex);
550+
copyHexToArray(key.contractID, accountIdHex);
551+
CHECK(
552+
toCerealCompact(key, "k") ==
553+
R"({"k":{"contractID":"CAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG67KRS","contentHash":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}})");
554+
}
555+
556+
// Check MuxedAccount (ED25519)
557+
{
558+
MuxedAccount ma;
559+
ma.type(KEY_TYPE_ED25519);
560+
copyHexToArray(ma.ed25519(), accountIdHex);
561+
CHECK(
562+
toCerealCompact(ma, "m") ==
563+
R"({"m":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"})");
564+
}
565+
566+
// Check MuxedAccount (MUXED_ED25519)
567+
{
568+
MuxedAccount ma;
569+
ma.type(KEY_TYPE_MUXED_ED25519);
570+
ma.med25519().id = 12345;
571+
copyHexToArray(ma.med25519().ed25519, accountIdHex);
572+
CHECK(
573+
toCerealCompact(ma, "m") ==
574+
R"({"m":{"id":12345,"accountID":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"}})");
575+
}
576+
577+
// Check Asset (NATIVE)
578+
{
579+
Asset a;
580+
a.type(ASSET_TYPE_NATIVE);
581+
CHECK(toCerealCompact(a, "a") == R"({"a":"NATIVE"})");
582+
}
583+
584+
// Check Asset (CREDIT_ALPHANUM4, valid code)
585+
{
586+
Asset a;
587+
a.type(ASSET_TYPE_CREDIT_ALPHANUM4);
588+
copyToArray(a.alphaNum4().assetCode, "USD");
589+
a.alphaNum4().issuer.type(PUBLIC_KEY_TYPE_ED25519);
590+
copyHexToArray(a.alphaNum4().issuer.ed25519(), accountIdHex);
591+
CHECK(
592+
toCerealCompact(a, "a") ==
593+
R"({"a":{"assetCode":"USD","issuer":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"}})");
594+
;
595+
}
596+
597+
// Check Asset (CREDIT_ALPHANUM12, valid code)
598+
{
599+
Asset a;
600+
a.type(ASSET_TYPE_CREDIT_ALPHANUM12);
601+
copyToArray(a.alphaNum12().assetCode, "USDC12");
602+
copyHexToArray(a.alphaNum12().issuer.ed25519(), accountIdHex);
603+
CHECK(
604+
toCerealCompact(a, "a") ==
605+
R"({"a":{"assetCode":"USDC12","issuer":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"}})");
606+
}
607+
608+
// Check Asset (CREDIT_ALPHANUM4, invalid code with embedded NUL)
609+
{
610+
Asset a;
611+
a.type(ASSET_TYPE_CREDIT_ALPHANUM4);
612+
copyToArray(a.alphaNum4().assetCode, std::string{'U', '\0', 'D', '\0'});
613+
copyHexToArray(a.alphaNum4().issuer.ed25519(), accountIdHex);
614+
CHECK(
615+
toCerealCompact(a, "a") ==
616+
R"({"a":{"assetCodeRaw":"55004400","issuer":"GAASGRLHRGV433YBENCWPCNLZXXQCI2FM6E2XTPPAERUKZ4JVPG66OUL"}})");
617+
}
618+
619+
// Check TrustLineAsset (POOL_SHARE)
620+
{
621+
TrustLineAsset tla;
622+
tla.type(ASSET_TYPE_POOL_SHARE);
623+
copyHexToArray(tla.liquidityPoolID(), accountIdHex);
624+
CHECK(
625+
toCerealCompact(tla, "a") ==
626+
R"({"a":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"})");
627+
}
628+
629+
// Check ChangeTrustAsset (POOL_SHARE)
630+
{
631+
ChangeTrustAsset cta;
632+
cta.type(ASSET_TYPE_POOL_SHARE);
633+
cta.liquidityPool().type(LIQUIDITY_POOL_CONSTANT_PRODUCT);
634+
auto& cp = cta.liquidityPool().constantProduct();
635+
cp.assetA.type(ASSET_TYPE_NATIVE);
636+
cp.assetB.type(ASSET_TYPE_NATIVE);
637+
cp.fee = 30;
638+
CHECK(toCerealCompact(cta, "a") ==
639+
R"({"a":{"assetA":"NATIVE","assetB":"NATIVE","fee":30}})");
640+
}
641+
642+
// Check enum
643+
{
644+
AssetType e = ASSET_TYPE_NATIVE;
645+
CHECK(toCerealCompact(e, "e") == R"({"e":"ASSET_TYPE_NATIVE"})");
646+
}
647+
648+
// Check pointer (null)
649+
{
650+
xdr::pointer<Asset> p;
651+
CHECK(toCerealCompact(p, "p") == R"({"p":null})");
652+
}
653+
654+
// Check pointer (non-null)
655+
{
656+
Asset a;
657+
a.type(ASSET_TYPE_NATIVE);
658+
xdr::pointer<Asset> p(new Asset{a});
659+
CHECK(toCerealCompact(p, "p") == R"({"p":"NATIVE"})");
660+
}
661+
662+
// Check nested pointer (null)
663+
{
664+
xdr::pointer<xdr::pointer<Asset>> p;
665+
CHECK(toCerealCompact(p, "p") == R"({"p":[]})");
666+
}
667+
668+
// Check nested pointer (outer non-null, inner null)
669+
{
670+
xdr::pointer<xdr::pointer<Asset>> p;
671+
p.reset(new xdr::pointer<Asset>{});
672+
CHECK(toCerealCompact(p, "p") == R"({"p":[null]})");
673+
}
674+
675+
// Check nested pointer (outer non-null, inner non-null)
676+
{
677+
Asset a;
678+
a.type(ASSET_TYPE_NATIVE);
679+
xdr::pointer<xdr::pointer<Asset>> p;
680+
p.reset(new xdr::pointer<Asset>{new Asset{a}});
681+
CHECK(toCerealCompact(p, "p") == R"({"p":["NATIVE"]})");
682+
}
683+
}
425684
} // namespace

0 commit comments

Comments
 (0)