Hook API Refactoring / Unit Testing (#581)

This commit is contained in:
tequ
2026-02-15 19:45:23 +09:00
committed by GitHub
parent fb7a0d71de
commit d209272379
12 changed files with 8820 additions and 2706 deletions

View File

@@ -18,7 +18,9 @@
//==============================================================================
#include <ripple/app/hook/Enum.h>
#include <ripple/app/hook/applyHook.h>
#include <ripple/basics/contract.h>
#include <ripple/protocol/Keylet.h>
#include <ripple/protocol/jss.h>
#include <stdexcept>
#include <test/jtx/hook.h>
@@ -102,6 +104,81 @@ hso(std::string const& wasmHex, void (*f)(Json::Value& jv))
return jv;
}
// Helper function to create HookContext with external stateMap
hook::HookContext
makeStubHookContext(
ripple::ApplyContext& applyCtx,
ripple::AccountID const& hookAccount,
ripple::AccountID const& otxnAccount,
StubHookContext const& stubHookContext,
hook::HookStateMap& stateMap)
{
auto& result = stubHookContext.result;
auto hookParams = result.hookParams.value_or(
std::map<std::vector<uint8_t>, std::vector<uint8_t>>{});
return hook::HookContext{
.applyCtx = applyCtx,
.slot = stubHookContext.slot,
.slot_free = stubHookContext.slot_free,
.slot_counter = stubHookContext.slot_counter,
.emit_nonce_counter = stubHookContext.emit_nonce_counter,
.ledger_nonce_counter = stubHookContext.ledger_nonce_counter,
.expected_etxn_count = stubHookContext.expected_etxn_count,
.nonce_used = stubHookContext.nonce_used,
.generation = stubHookContext.generation,
.burden = stubHookContext.burden,
.guard_map = stubHookContext.guard_map,
.result =
{
.hookSetTxnID = result.hookSetTxnID,
.hookHash = result.hookHash,
.hookCanEmit = result.hookCanEmit,
.accountKeylet = keylet::account(hookAccount),
.hookKeylet = keylet::hook(hookAccount),
.account = hookAccount,
.otxnAccount = otxnAccount,
.hookNamespace = result.hookNamespace,
.emittedTxn = result.emittedTxn,
.stateMap = stateMap,
.changedStateCount = result.changedStateCount,
.hookParamOverrides = result.hookParamOverrides,
.hookParams = hookParams,
.hookSkips = result.hookSkips,
.exitType = result.exitType,
.exitReason = result.exitReason,
.exitCode = result.exitCode,
.instructionCount = result.instructionCount,
.hasCallback = result.hasCallback,
.isCallback = result.isCallback,
.isStrong = result.isStrong,
.wasmParam = result.wasmParam,
.overrideCount = result.overrideCount,
.hookChainPosition = result.hookChainPosition,
.foreignStateSetDisabled = result.foreignStateSetDisabled,
.executeAgainAsWeak = result.executeAgainAsWeak,
.provisionalMeta = result.provisionalMeta,
},
.emitFailure = stubHookContext.emitFailure,
.module = nullptr};
}
// Original function - WARNING: stateMap reference may become dangling
// Only use when stateMap access is not needed after HookContext creation
hook::HookContext
makeStubHookContext(
ripple::ApplyContext& applyCtx,
ripple::AccountID const& hookAccount,
ripple::AccountID const& otxnAccount,
StubHookContext const& stubHookContext)
{
// Use thread_local to keep stateMap alive
// Note: This is a workaround; each call resets the stateMap
thread_local hook::HookStateMap stateMap;
stateMap = stubHookContext.result.stateMap.value_or(hook::HookStateMap{});
return makeStubHookContext(
applyCtx, hookAccount, otxnAccount, stubHookContext, stateMap);
}
} // namespace jtx
} // namespace test
} // namespace ripple