> subsystem-summary-of-test
read this skill for a token-efficient summary of the test subsystem
curl "https://skillshub.wtf/stellar/stellar-core/subsystem-summary-of-test?format=md"Test Subsystem — Test Utilities and Infrastructure
The src/test/ directory contains test infrastructure, helpers, and utilities used across the entire stellar-core test suite. It does NOT contain the actual test cases (those live alongside their subsystems). This document covers the test framework, helper classes, and conventions.
Test Framework and Runner (test.h / test.cpp)
Test Entry Point
runTest(CommandLineArgs const& args)— Main test runner entry point. Configures Catch2 session, parses CLI args (log level, metrics, version selection, tx meta recording), seeds PRNGs, and runs all tests.- Uses Catch2 as the underlying test framework (wrapped via
Catch2.h).
Test Configuration
getTestConfig(int instanceNumber, Config::TestDbMode mode)— Returns a lazily-created, cachedConfigfor the given instance number. Configs are stored ingTestCfg[mode]arrays. Default mode isTESTDB_BUCKET_DB_VOLATILE. Key config settings:RUN_STANDALONE = true,FORCE_SCP = true,MANUAL_CLOSE = trueWORKER_THREADS = 3, invariant checks enabled (exceptEventsAreConsistentWithEntryDiffs)- Test root directories created via
TmpDiringTestRoots - Node seed derived deterministically from instance number + command-line seed
- Single-node quorum with
UNSAFE_QUORUM = true NETWORK_PASSPHRASE = "(V) (;,,;) (V)"- DB can be in-memory SQLite, file-backed SQLite, or PostgreSQL
Version Testing Helpers
The framework supports running tests across multiple protocol versions:
for_all_versions(app, f)— Runffor every protocol version (1 to current).for_versions(from, to, app, f)— Runffor versions in range[from, to].for_versions_from(from, app, f)— Runffor versions[from, current].for_versions_to(to, app, f)— Runffor versions[1, to].for_all_versions_except(versions, app, f)— Runffor all versions except those listed.TEST_CASE_VERSIONS(name, filters)macro — Declares a test that iterates over all versions specified via--versionor--all-versionsCLI flags.test_versions_wrapper(f)— Internal: iteratesgVersionsToTest, setsgTestingVersion, clears configs, and runsfinside a Catch2SECTIONfor each version.- Internally relies on
gMustUseTestVersionsWrapperflag to enforce correct usage.
PRNG and Determinism
ReseedPRNGListener— Catch2 event listener that re-seeds all PRNGs at the start of every test case usingreinitializeAllGlobalStateWithSeed(sCommandLineSeed). The seed rotates every 24 hours by default.- Node secret keys derived from
0xFFFF0000 + (instanceNumber ^ lastGlobalStateSeed)to avoid inter-test collisions.
Transaction Metadata Recording/Checking
recordOrCheckGlobalTestTxMetadata(TransactionMeta const& txMeta)— Records or checks a SIPHash of normalized tx metadata against a persistent baseline.TestTxMetaModeenum:META_TEST_IGNORE,META_TEST_RECORD,META_TEST_CHECK.TestContextListener— Catch2 listener tracking current test case and sections for metadata context keying.- Baselines stored as JSON files with base64-encoded hashes per test case/section. CLI flags:
--record-test-tx-meta DIR,--check-test-tx-meta DIR,--debug-test-tx-meta FILE. saveTestTxMeta()/loadTestTxMeta()/reportTestTxMeta()manage persistence.
Utility Functions
getSrcTestDataPath(rel)/getBuildTestDataPath(rel)— Resolve paths undertestdata/relative to source or build dir.cleanupTmpDirs()— ClearsgTestRoots(must be called manually ifgetTestConfigused outside Catch2).gBaseInstance— Global offset for test instance numbering (for parallel test execution).force_sqlite— Set viaSTELLAR_FORCE_SQLITEenv var.
TestAccount (TestAccount.h / TestAccount.cpp)
A high-level wrapper around a Stellar account for test convenience. Encapsulates Application&, SecretKey, and SequenceNumber.
Construction
TestAccount(app, secretKey, seqNum=0)— Wraps an existing secret key.
Account Operations (all apply transactions and assert success)
create(secretKey, initialBalance)/create(name, initialBalance)— Create a sub-account, returns newTestAccount.createBatch(secretKeys, initialBalance)— Batch create multiple accounts.merge(into)— Merge this account into another.pay(destination, amount)/pay(destination, asset, amount)— Send payment.pay(destination, sendCur, sendMax, destCur, destAmount, path)— Path payment strict receive.pathPaymentStrictSend(...)— Path payment strict send.changeTrust(asset, limit)— Establish/modify trustline.allowTrust(asset, trustor, ...)/denyTrust(...)/allowMaintainLiabilities(...)— Manage trust authorization.setTrustLineFlags(asset, trustor, args)— Set trust line flags.setOptions(args)— Set account options.manageData(name, value)— Set/delete data entries.bumpSequence(to)— Bump sequence number.manageOffer(...)/manageBuyOffer(...)/createPassiveOffer(...)— DEX operations, return offer ID.createClaimableBalance(...)/claimClaimableBalance(...)— Claimable balance ops.clawback(...)/clawbackClaimableBalance(...)— Clawback operations.liquidityPoolDeposit(...)/liquidityPoolWithdraw(...)— AMM operations.inflation()— Run inflation.
Query Methods
getBalance()/getAvailableBalance()— Native balance queries.getTrustlineBalance(asset)/getTrustlineFlags(asset)— Trustline queries.loadTrustLine(asset)/hasTrustLine(asset)— Load/check trustlines.getNumSubEntries()— Sub-entry count.exists()— Check if account exists on ledger.loadSequenceNumber()/getLastSequenceNumber()/nextSequenceNumber()— Sequence number management. Auto-loads from ledger ifmSn == 0.
Transaction Building
tx(ops, seqNum)— Build aTransactionTestFramePtrfrom operations, auto-incrementing sequence.op(operation)— Set source account on an operation to this account.applyOpsBatch(ops)— Apply operations in batches ofMAX_OPS_PER_TX, closing ledgers.
Implicit Conversions
- Converts to
SecretKeyandPublicKeyimplicitly.
TxTests (TxTests.h / TxTests.cpp)
The stellar::txtest namespace contains the bulk of transaction test utilities: operation builders, transaction constructors, apply helpers, and ledger close wrappers.
Transaction Application
applyCheck(tx, app, checkSeqNum)— The core test-apply function. Closes a ledger, then in aLedgerTxn: validates tx (checkValidForTesting), processes fees, applies tx, verifies results match between original and cloned tx, checks sequence number changes, verifies no unexpected ledger mutations on failure, commits, and records tx metadata. Returns success bool.applyTx(tx, app, checkSeqNum)— Applies a tx (viaapplyCheckfor in-memory mode, orcloseLedgerfor BucketListDB). CallsthrowIfon failure, checks fee charged.validateTxResults(tx, app, validationResult, applyResult)— Validates thatcheckValidandapplyproduce expected results.
Ledger Close Helpers
closeLedger(app, txs, strictOrder, upgrades)— Close the next ledger with the given transactions and upgrades.closeLedgerOn(app, day, month, year, txs)— Close ledger with a specific date.closeLedgerOn(app, ledgerSeq, closeTime, txs, strictOrder, upgrades, parallelSorobanOrder)— Full-control ledger close. Builds aTxSetXDRFrame, externalizes via Herder, cranks until the ledger closes.closeLedger(app, txSet)— Close with a pre-built tx set.- When
strictOrder = true, transactions are applied in exact order (allows intentionally invalid txs). Otherwise,checkValidis asserted.
Transaction Constructors
transactionFromOperations(app, from, seq, ops, fee, memo)— Creates V0 or V1 envelope based on protocol version.transactionFromOperationsV0(...)/transactionFromOperationsV1(...)— Explicit version constructors.paddedTransactionFromOperations(...)/paddedTransactionFromOperationsV1(...)— Create transactions padded to a desired byte size (V23+).transactionWithV2Precondition(app, account, seqDelta, fee, cond)— Transaction with V2 preconditions.feeBump(app, feeSource, tx, inclusion, useInclusionAsFullFee)— Create a fee bump transaction.transactionFrameFromOps(networkID, source, ops, opKeys, cond)— Direct envelope construction with explicit signers.sorobanTransactionFrameFromOps(...)/sorobanTransactionFrameFromOpsWithTotalFee(...)— Soroban transaction construction with resources, fees.
Operation Builders (all return Operation)
- Account:
createAccount(dest, amount),accountMerge(dest) - Payments:
payment(to, amount),payment(to, asset, amount),pathPayment(...),pathPaymentStrictSend(...) - Trust:
changeTrust(asset, limit),allowTrust(trustor, asset, authorize),setTrustLineFlags(trustor, asset, args) - DEX:
manageOffer(...),manageBuyOffer(...),createPassiveOffer(...) - Data:
manageData(name, value),bumpSequence(to) - Claimable Balance:
createClaimableBalance(...),claimClaimableBalance(...) - Sponsorship:
beginSponsoringFutureReserves(...),endSponsoringFutureReserves(),revokeSponsorship(...) - Clawback:
clawback(from, asset, amount),clawbackClaimableBalance(...) - Liquidity Pool:
liquidityPoolDeposit(...),liquidityPoolWithdraw(...) - Inflation:
inflation() - Soroban:
createUploadWasmOperation(generatedWasmSize, wasmSeed),createUploadWasmTx(...) - SetOptions builders:
setMasterWeight(w),setLowThreshold(t),setMedThreshold(t),setHighThreshold(t),setSigner(s),setFlags(f),clearFlags(f),setInflationDestination(id),setHomeDomain(d)— returnSetOptionsArguments, composable withoperator|.
Apply Helpers
applyManageOffer(...)/applyManageBuyOffer(...)/applyCreatePassiveOffer(...)— Apply offer operations and verify ledger state, return offer ID.
Asset Builders
makeNativeAsset(),makeInvalidAsset(),makeAsset(issuer, code),makeAssetAlphanum12(issuer, code),makeChangeTrustAssetPoolShare(assetA, assetB, fee)
Upgrade Helpers
executeUpgrade(app, lupgrade)/executeUpgrades(app, upgrades)— Apply ledger upgrades and return resulting header.makeConfigUpgradeSet(ltx, configUpgradeSet)— Create a config upgrade set entry in the ledger.makeConfigUpgrade(configUpgradeSet)— Create aLedgerUpgradefrom a config upgrade set.makeBaseReserveUpgrade(baseReserve)— Create a base reserve upgrade.
Query Helpers
getRoot(networkID)/getAccount(name)— Get root or named test account keys.loadAccount(ltx, k)/doesAccountExist(app, k)— Account existence checks.getAccountSigners(k, app)— Get signers for an account.checkLiquidityPool(app, poolID, ...)— Assert liquidity pool state.getBalance(app, accountID, asset)— Get balance for any asset type.getLclProtocolVersion(app)— Get last closed ledger protocol version.isSuccessResult(res)— Check if result is success (including fee bump inner success).getGenesisAccount(app, accountIndex)— Get a genesis test account.sorobanResourceFee(app, resources, txSize, eventsSize, ...)— Compute Soroban resource fee.
Result Inspection
getFirstResult(tx)/getFirstResultCode(tx)— Get first operation result.checkTx(index, resultSet, expected)— Assert transaction result code at index.expectedResult(fee, opsCount, code, ops)— Build an expectedTransactionResult.sign(networkID, key, env)— Sign a V1 envelope.
Structs
ExpectedOpResult— WrapsOperationResultwith constructors for various result codes.ValidationResult— Pair of{fee, TransactionResultCode}.SetOptionsArguments— Optional fields for set_options, composable viaoperator|.SetTrustLineFlagsArguments—{setFlags, clearFlags}, composable viaoperator|.
TestMarket (TestMarket.h / TestMarket.cpp)
Tracks DEX offer state for verification in tests.
Key Types
OfferKey—{sellerID, offerID}, ordered by seller then ID.OfferState—{selling, buying, price, amount, type}. Sentinel values:OfferState::SAME(no change expected),OfferState::DELETED(offer removed, amount=0).TestMarketOffer—{OfferKey, OfferState}, withexchanged(ledgerVersion, sold, bought)returning aClaimAtom.TestMarketBalance/TestMarketBalances— For balance verification.
TestMarket Class
TestMarket(app)— OwnsmOffersmap andmLastAddedID.addOffer(account, state, finishedState)— Create an offer, verify ID assignment.updateOffer(account, id, state, finishedState)— Update existing offer.requireChanges(changes, f)— Executef, then verify offer state changes match expectations. On exception, verifies no unintended changes.requireChangesWithOffer(changes, f)— LikerequireChangesbutfreturns the new offer.requireBalances(balances)— Assert account balances match expectations.checkCurrentOffers()— Verify all tracked offers match ledger state.checkState(offers, deletedOffers)— Internal: verify offers exist/deleted in ledger.
TestUtils (TestUtils.h / TestUtils.cpp)
Clock/Crank Helpers (testutil namespace)
crankSome(clock)— Crank up to 100 times or 1 second.crankFor(clock, duration)— Crank until duration elapsed.crankUntil(app, predicate, timeout)— Crank until predicate is true or timeout.shutdownWorkScheduler(app)— Shut down work scheduler and crank until aborted.
Test Application
TestApplication— Subclass ofApplicationImplthat overridescreateInvariantManager()to return aTestInvariantManager.TestInvariantManager— Subclass ofInvariantManagerImplthat throwsInvariantDoesNotHoldon invariant failure instead of aborting (enables testing invariant violations).createTestApplication<T>(clock, cfg, newDB, startApp)— Template factory. Creates, adjusts config, optionally starts the application.
BucketList Helpers
BucketListDepthModifier<BucketT>— RAII class that temporarily modifiesBucketListBase<BucketT>::kNumLevels, restores on destruction. Instantiated forLiveBucketandHotArchiveBucket.testBucketMetadata(protocolVersion)— CreateBucketMetadatawith appropriate version/type fields.
Date/Time Helpers
getTestDate(day, month, year)— ReturnsTimePoint.getTestDateTime(day, month, year, hour, minute, second)— Returnsstd::tm.genesis(minute, second)— Returns a system_time_point at July 1, 2014.
Soroban Network Config Helpers
setSorobanNetworkConfigForTest(cfg, ledgerVersion)— Sets generous defaults for Soroban config (large limits for instructions, data sizes, etc.).overrideSorobanNetworkConfigForTest(app)— Apply test Soroban config via full upgrade process.upgradeSorobanNetworkConfig(modifyFn, simulation, applyUpgrade)— Run loadgen-based config upgrade across a simulation.prepareSorobanNetworkConfigUpgrade(app, modifyFn)— Full 4-step upgrade preparation: deploy wasm, create instance, create upgrade entry, arm.modifySorobanNetworkConfig(app, modifyFn)— Full 5-step upgrade including closing the armed ledger.
Other Utilities
getInvalidAssets(issuer)— Generate a vector of invalid assets for negative testing.computeMultiplier(le)— Compute reserve multiplier for a ledger entry.appProtocolVersionStartsFrom(app, fromVersion)— Check if app's ledger version is >= a given version.DEFAULT_TEST_RESOURCE_FEE = 1'000'000— Constant for Soroban test fees.generateTransactions(app, outputFile, numTransactions, accounts, offset)— Generate payment transactions to a file usingTxGenerator.
TestExceptions (TestExceptions.h / TestExceptions.cpp)
Exception-based error reporting for transaction test results.
throwIf(TransactionResult const& result)— Examines a transaction result and throws a typed exception for each possible error code across all operation types.ex_txException— Base class for all test exceptions.TEST_EXCEPTION(M)macro — Generates exception classes likeex_CREATE_ACCOUNT_MALFORMED,ex_PAYMENT_UNDERFUNDED, etc.- Covers all operation types: CreateAccount, Payment, PathPayment (strict receive/send), ManageSellOffer, ManageBuyOffer, SetOptions, ChangeTrust, AllowTrust, AccountMerge, Inflation, ManageData, BumpSequence, CreateClaimableBalance, ClaimClaimableBalance, Clawback, SetTrustLineFlags, LiquidityPoolDeposit, LiquidityPoolWithdraw, InvokeHostFunction, ExtendFootprintTTL, RestoreFootprint.
- Also transaction-level exceptions:
ex_txBAD_SEQ,ex_txNO_ACCOUNT,ex_txINTERNAL_ERROR,ex_txINSUFFICIENT_BALANCE,ex_txBAD_AUTH.
Catch2 Integration (Catch2.h / Catch2.cpp)
Catch2.h— Central include point for Catch2 (lib/catch.hpp). DefinesStringMakerspecializations for XDR types (usingxdr_to_string),OfferState,CatchupRange, andCatchupPerformedWorkfor pretty-printing in test output.Catch2.cpp— Implements theStringMaker::convertmethods.
SimpleTestReporter (SimpleTestReporter.h)
Custom Catch2 reporter for minimal output:
- Prints test case name and source location on start.
- Prints dots for section progress (controllable via
gDisableDots). - Only reports assertion details on failure.
- Registered as
"simple"reporter.
Fuzzing Infrastructure (Fuzzer.h, FuzzerImpl.h, FuzzerImpl.cpp, fuzz.h, fuzz.cpp)
Fuzzer Base Class
Fuzzer— Abstract interface withinject(filename),initialize(),shutdown(),genFuzz(filename),xdrSizeLimit().
TransactionFuzzer
- Sets up a minimal ledger state with pregened accounts, trustlines, offers, claimable balances, and liquidity pools.
inject()reads fuzzed XDR operations from a file, builds a transaction, and applies it.- Initialization: creates
NUMBER_OF_PREGENERATED_ACCOUNTS(5) accounts with trustlines, assets, offers, etc. - Uses compact key encoding (
getShortKey/setShortKey) to map fuzzed bytes to valid account/asset/ledger key references. FuzzUtilsnamespace constants:NUM_STORED_LEDGER_KEYS = 0x100,NUM_UNVALIDATED_LEDGER_KEYS = 0x40,NUM_STORED_POOL_IDS = 0x7.
OverlayFuzzer
- Creates a 2-node
Simulation(acceptor + initiator). inject()reads aStellarMessagefrom file and delivers it to the acceptor's peer connection.
Fuzz Entry Point
fuzz(filename, metrics, processID, fuzzerMode)— Creates fuzzer, initializes, runs inject loop (with__AFL_LOOPfor AFL persistent mode).FuzzUtils::createFuzzer(processID, mode)— Factory for fuzzer instances.
How Tests Are Structured and Run
- Test cases use Catch2 macros (
TEST_CASE,SECTION) and live alongside their subsystem code (not insrc/test/). - Test setup typically: get config via
getTestConfig(), createVirtualClock, createTestApplicationviacreateTestApplication(). - Account creation: Use root
TestAccountfromgetRoot(networkID), thenroot.create(...)to make sub-accounts. - Transaction testing: Build operations (e.g.,
payment(),createAccount()), wrap intransactionFromOperations(), apply withapplyTx()orcloseLedger(). - Version iteration: Use
for_versions(...)orTEST_CASE_VERSIONSto test across protocol versions. - Error testing: Operations that should fail throw typed exceptions from
TestExceptions.h; useREQUIRE_THROWS_AS(...)to catch them. - DEX testing: Use
TestMarketto track and verify offer state changes. - Soroban testing: Use
sorobanTransactionFrameFromOps()withSorobanResources, apply viacloseLedger(). UseoverrideSorobanNetworkConfigForTest()for generous limits.
Ownership and Relationships
TestAccountholds a reference toApplication&and ownsSecretKey+ sequence number.TestMarketholds a reference toApplication&and owns amap<OfferKey, OfferState>.TestApplicationinherits fromApplicationImpl, owns aTestInvariantManager.getTestConfig()returns references to globally cachedConfigobjects ingTestCfg[].TransactionTestFramePtr(fromtransactions/test/TransactionTestFrame.h) wrapsTransactionFrameBasewith test-specific methods likeoverrideResult()andaddSignature().- Test temp directories are managed via
gTestRootsvector ofTmpDirobjects.
> related_skills --same-repo
> validating-a-change
comprehensive validation of a change to ensure it is correct and ready for a pull request
> regenerating a technical summary of stellar-core
Instructions for regenerating the full set of subsystem and whole-system technical summary skill documents for stellar-core
> subsystem-summary-of-work
read this skill for a token-efficient summary of the work subsystem
> subsystem-summary-of-util
read this skill for a token-efficient summary of the util subsystem