#include #include namespace ripple { class Memo_test : public beast::unit_test::suite { public: void testMemos() { testcase("Test memos"); using namespace test::jtx; Account alice{"alice"}; Env env(*this); env.fund(XRP(10000), alice); env.close(); // Lambda that returns a valid JTx with a memo that we can hack up. // This is the basis for building tests of invalid states. auto makeJtxWithMemo = [&env, &alice]() { JTx example = noop(alice); memo const exampleMemo{"tic", "tac", "toe"}; exampleMemo(env, example); return example; }; // A valid memo. env(makeJtxWithMemo()); env.close(); { // Make sure that too big a memo is flagged as invalid. JTx memoSize = makeJtxWithMemo(); memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] [sfMemoData.jsonName] = std::string(2020, '0'); env(memoSize, rpc("invalidTransaction", "fails local checks: The memo exceeds the maximum allowed " "size.")); // This memo is just barely small enough. memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] [sfMemoData.jsonName] = std::string(2018, '1'); env(memoSize); } { // Put a non-Memo in the Memos array. JTx memoNonMemo = noop(alice); auto& jv = memoNonMemo.jv; auto& ma = jv[sfMemos.jsonName]; auto& mi = ma[ma.size()]; auto& m = mi[sfCreatedNode.jsonName]; // CreatedNode in Memos m[sfMemoData.jsonName] = "3030303030"; env(memoNonMemo, rpc("invalidTransaction", "fails local checks: A memo array may contain only Memo " "objects.")); } { // Put an invalid field in a Memo object. JTx memoExtra = makeJtxWithMemo(); memoExtra .jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfFlags.jsonName] = 13; env(memoExtra, rpc("invalidTransaction", "fails local checks: A memo may contain only MemoType, " "MemoData or MemoFormat fields.")); } { // Put a character that is not allowed in a URL in a MemoType field. JTx memoBadChar = makeJtxWithMemo(); memoBadChar.jv[sfMemos.jsonName][0u][sfMemo.jsonName] [sfMemoType.jsonName] = strHex(std::string_view("ONE