fix: Make Wasm_tests.cpp run again

This commit is contained in:
TimothyBanks
2026-08-17 15:01:46 -04:00
parent c5524e4881
commit 7122bb8a43
4 changed files with 22 additions and 239 deletions

View File

@@ -140,7 +140,9 @@ public:
return Bytes{s.begin(), s.end()};
}
return std::unexpected(HostFunctionError::Unimplemented);
// FieldNotFound is a guest-returnable code (the contract handles a negative result);
// Unimplemented now maps to a fatal Fault::Internal (tecINTERNAL) that stops the run.
return std::unexpected(HostFunctionError::FieldNotFound);
}
[[nodiscard]] std::expected<Bytes, HostFunctionError>

View File

@@ -1,15 +1,17 @@
// Not built. These suites drive a C++ wasm engine interface -- WasmVM over the wasm.h C API,
// HostFuncWrapper, WasmImportsHelper -- that this tree does not provide; the VM lives in the
// Rust crates. Kept as the coverage target for the port. The body is one comment block, and
// the fixtures it reads (wasm_fixtures/fixtures.cpp) are disabled the same way; re-enabling
// the suites means uncommenting both.
/*
#include <expected>
#ifdef _DEBUG
// #define DEBUG_OUTPUT 1
#endif
// The wasm engine is now the Rust `xrpl-wasm-vm` crate, reached only through
// `runEscrowWasm` / `preflightEscrowWasm`. The old C++ engine surface this suite used for
// its lower-level cases -- `WasmEngine`, `createWasmImport` / `WasmImpFunc` /
// `WASM_IMPORT_FUNC2` (arbitrary host imports), and `wasmParams` -- no longer exists, so the
// tests built on it (raw `addTwo` module, ledger-sqn/host-function-cost engine runs, bad
// alignment) were removed; that engine/ABI coverage now lives in the crate tests
// (`crates/xrpl-wasm-vm/tests/budgets.rs`, `memory_policy.rs`). What remains here is the
// app-tier escrow integration that still runs through `runEscrowWasm`.
#include <test/app/TestHostFunctions.h>
#include <test/app/wasm_fixtures/fixtures.h>
#include <test/jtx/Env.h>
@@ -18,15 +20,11 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncWrapper.h> // IWYU pragma: keep
#include <xrpl/tx/wasm/WasmCommon.h>
#include <xrpl/tx/wasm/WasmImportsHelper.h>
#include <xrpl/tx/wasm/WasmVM.h>
#include <boost/algorithm/hex.hpp>
#include <wasm.h>
#include <cstdint>
#include <limits>
#include <source_location>
@@ -35,20 +33,6 @@
namespace xrpl::test {
bool
testGetDataIncrement();
using Add_proto = int32_t(int32_t, int32_t);
static wasm_trap_t*
add(HostFunctions&, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
int32_t const val1 = params->data[0].of.i32;
int32_t const val2 = params->data[1].of.i32;
// printf("Host function \"Add\": %d + %d\n", Val1, Val2);
results->data[0] = WASM_I32_VAL(val1 + val2);
return nullptr;
}
std::vector<uint8_t>
hexToBytes(std::string const& hex)
{
@@ -73,59 +57,6 @@ struct Wasm_test : public beast::unit_test::Suite
}
}
void
testGetDataHelperFunctions()
{
testcase("getData helper functions");
BEAST_EXPECT(testGetDataIncrement());
}
void
testWasmLib()
{
testcase("wasm lib test");
// clang-format off
// The WASM module buffer. //
Bytes const wasm = {// WASM header //
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00,
// Type section //
0x01, 0x07, 0x01,
// function type {i32, i32} -> {i32} //
0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F,
// Import section //
0x02, 0x13, 0x01,
// module name: "extern" //
0x06, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6E,
// extern name: "func-add" //
0x08, 0x66, 0x75, 0x6E, 0x63, 0x2D, 0x61, 0x64, 0x64,
// import desc: func 0 //
0x00, 0x00,
// Function section //
0x03, 0x02, 0x01, 0x00,
// Export section //
0x07, 0x0A, 0x01,
// export name: "addTwo" //
0x06, 0x61, 0x64, 0x64, 0x54, 0x77, 0x6F,
// export desc: func 0 //
0x00, 0x01,
// Code section //
0x0A, 0x0A, 0x01,
// code body //
0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x0B};
// clang-format on
auto& vm = WasmEngine::instance();
HostFunctions hfs;
ImportVec imports;
WasmImpFunc<Add_proto>(imports, "func-add", add, hfs);
auto re = vm.run(wasm, hfs, 10'000'000, "addTwo", wasmParams(1234, 5678), imports);
// if (res) printf("invokeAdd get the result: %d\n", res.value());
checkResult(re, 6'912, 59);
}
void
testBadWasm()
{
@@ -140,7 +71,7 @@ struct Wasm_test : public beast::unit_test::Suite
auto wasm = hexToBytes("00000000");
std::string const funcName("mock_escrow");
auto re = runEscrowWasm(wasm, hfs, 15, funcName, {});
auto re = runEscrowWasm(wasm, hfs, 15, funcName);
BEAST_EXPECT(!re);
}
@@ -148,7 +79,7 @@ struct Wasm_test : public beast::unit_test::Suite
auto wasm = hexToBytes("00112233445566778899AA");
std::string const funcName("mock_escrow");
auto const re = preflightEscrowWasm(wasm, hfs, funcName);
auto const re = preflightEscrowWasm(wasm, env.journal, funcName);
BEAST_EXPECT(!isTesSuccess(re));
}
@@ -169,112 +100,11 @@ struct Wasm_test : public beast::unit_test::Suite
"732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a"
"6d756c746976616c7565");
auto const re = preflightEscrowWasm(badWasm, hfs, escrowFunctionName);
auto const re = preflightEscrowWasm(badWasm, env.journal, escrowFunctionName);
BEAST_EXPECT(!isTesSuccess(re));
}
}
void
testWasmLedgerSqn()
{
testcase("Wasm get ledger sequence");
auto ledgerSqnWasm = hexToBytes(kLedgerSqnWasmHex);
using namespace test::jtx;
Env env{*this};
TestLedgerDataProvider hfs(env);
ImportVec imports;
WASM_IMPORT_FUNC2(imports, getLedgerSqn, "ldgr_index", hfs, 33);
auto& engine = WasmEngine::instance();
auto re =
engine.run(ledgerSqnWasm, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal);
checkResult(re, 0, 440);
env.close();
env.close();
// empty module, throwing exception
re = engine.run({}, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal);
BEAST_EXPECT(!re);
env.close();
}
void
testHFCost()
{
testcase("wasm test host functions cost");
using namespace test::jtx;
Env env(*this);
{
auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env);
auto imp = createWasmImport(hfs);
for (auto& i : imp)
i.second.second.gas = 0;
auto re = engine.run(
allHostFuncWasm, hfs, 1'000'000, escrowFunctionName, {}, imp, env.journal);
checkResult(re, 1, 30'760);
env.close();
}
env.close();
env.close();
env.close();
env.close();
env.close();
{
auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env);
auto const imp = createWasmImport(hfs);
auto re = engine.run(
allHostFuncWasm, hfs, 1'000'000, escrowFunctionName, {}, imp, env.journal);
checkResult(re, 1, 48'580);
env.close();
}
// not enough gas
{
auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env);
auto const imp = createWasmImport(hfs);
auto re =
engine.run(allHostFuncWasm, hfs, 200, escrowFunctionName, {}, imp, env.journal);
if (BEAST_EXPECT(!re))
{
// Running out of gas now terminates with tecOUT_OF_GAS (was
// previously collapsed into tecFAILED_PROCESSING).
BEAST_EXPECTS(
re.error().ter == tecOUT_OF_GAS, std::to_string(TERtoInt(re.error().ter)));
}
env.close();
}
}
void
testEscrowWasmDN()
{
@@ -286,14 +116,14 @@ struct Wasm_test : public beast::unit_test::Suite
Env env{*this};
{
TestHostFunctions hfs(env);
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {});
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName);
checkResult(re, 1, 48'580);
}
{
// Invalid gas limit (0) should be rejected (boundary condition)
TestHostFunctions hfs(env);
auto re = runEscrowWasm(allHFWasm, hfs, -1, escrowFunctionName, {});
auto re = runEscrowWasm(allHFWasm, hfs, -1, escrowFunctionName);
BEAST_EXPECT(!re.has_value());
BEAST_EXPECT(re.error().ter == temBAD_AMOUNT);
}
@@ -301,7 +131,7 @@ struct Wasm_test : public beast::unit_test::Suite
{
// Invalid gas limit (-1) should be rejected
TestHostFunctions hfs(env);
auto re = runEscrowWasm(allHFWasm, hfs, 0, escrowFunctionName, {});
auto re = runEscrowWasm(allHFWasm, hfs, 0, escrowFunctionName);
BEAST_EXPECT(!re.has_value());
BEAST_EXPECT(re.error().ter == temBAD_AMOUNT);
}
@@ -310,7 +140,7 @@ struct Wasm_test : public beast::unit_test::Suite
// max<int64_t>() gas
TestHostFunctions hfs(env);
auto re = runEscrowWasm(
allHFWasm, hfs, std::numeric_limits<int64_t>::max(), escrowFunctionName, {});
allHFWasm, hfs, std::numeric_limits<int64_t>::max(), escrowFunctionName);
checkResult(re, 1, 48'580);
}
@@ -328,7 +158,7 @@ struct Wasm_test : public beast::unit_test::Suite
};
FieldNotFoundHostFunctions hfs(env);
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {});
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName);
checkResult(re, -201, 28'329);
}
@@ -346,7 +176,7 @@ struct Wasm_test : public beast::unit_test::Suite
};
OversizedFieldHostFunctions hfs(env);
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {});
auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName);
checkResult(re, -201, 28'329);
}
}
@@ -364,39 +194,11 @@ struct Wasm_test : public beast::unit_test::Suite
TestHostFunctions hfs(env);
auto const allowance = 125'667;
auto re = runEscrowWasm(codecovWasm, hfs, allowance, escrowFunctionName, {});
auto re = runEscrowWasm(codecovWasm, hfs, allowance, escrowFunctionName);
checkResult(re, 1, allowance);
}
void
testBadAlign()
{
testcase("Wasm Bad Align");
// bad_align.c
auto const badAlignWasm = hexToBytes(kBadAlignWasmHex);
using namespace test::jtx;
Env env{*this};
TestHostFunctions hfs(env);
auto imports = createWasmImport(hfs);
{ // Calls float_from_uint with bad alignment.
// Can be checked through codecov
auto& engine = WasmEngine::instance();
auto re = engine.run(badAlignWasm, hfs, 1'000'000, "test", {}, imports, env.journal);
if (BEAST_EXPECTS(re, transToken(re.error().ter)))
{
BEAST_EXPECTS(re->result == 0x47308594, std::to_string(re->result));
}
}
env.close();
}
void
testSwapBytes()
{
@@ -454,19 +256,9 @@ struct Wasm_test : public beast::unit_test::Suite
void
run() override
{
using namespace test::jtx;
testGetDataHelperFunctions();
testWasmLib();
testBadWasm();
testWasmLedgerSqn();
testHFCost();
testEscrowWasmDN();
testCodecovWasm();
testBadAlign();
testSwapBytes();
}
};
@@ -474,4 +266,3 @@ struct Wasm_test : public beast::unit_test::Suite
BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl);
} // namespace xrpl::test
*/

View File

@@ -1,10 +1,3 @@
// Not built. The only reader of these blobs is the disabled suite in Wasm_test.cpp, so they
// are left out of the build and cost neither a translation unit nor static-init time.
// Regenerate the hex with copyFixtures.py.
//
// TODO: consider moving these to separate files (and figure out the build)
/*
#include <test/app/wasm_fixtures/fixtures.h>
#include <string>
@@ -654,4 +647,3 @@ extern std::string const kBadAlignWasmHex =
"32393538616631656533303861373930636664623432626432343732302900490f7461726765745f66656174757265"
"73042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b"
"0a6d756c746976616c7565";
*/

View File

@@ -1,7 +1,5 @@
#pragma once
// TODO: consider moving these to separate files (and figure out the build)
#include <string>
extern std::string const kLedgerSqnWasmHex;