ci: Improve test debuggability (#7619)

Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
This commit is contained in:
Mayukha Vadari
2026-07-21 09:14:40 -04:00
committed by Gregory Tsipenyuk
parent 6154f02e85
commit 41034386a1
2 changed files with 49 additions and 38 deletions

View File

@@ -223,11 +223,13 @@ jobs:
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
set -o pipefail
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
--target "${CMAKE_TARGET}" \
2>&1 | tee "${GITHUB_WORKSPACE}/build.log"
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
@@ -322,7 +324,7 @@ jobs:
PRELOAD=""
fi
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee "${GITHUB_WORKSPACE}/unittest.log"
# Smoke-run every benchmark module with a single repetition to confirm the
# benchmarks still build and execute. This is a correctness check, not a
@@ -341,25 +343,27 @@ jobs:
done < <(find src/benchmarks -type f -perm -u+x -name 'xrpl.bench.*')
exit "${rc}"
- name: Show test failure summary
if: ${{ failure() && !inputs.build_only }}
env:
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
- name: Show build/test failure summary
if: ${{ failure() }}
run: |
if [ ! -d "${WORKING_DIR}" ]; then
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
fi
cd "${GITHUB_WORKSPACE}"
cd "${WORKING_DIR}"
if [ ! -f unittest.log ]; then
echo "unittest.log not found; embedded tests may not have run."
exit 0
fi
if ! grep -E "failed" unittest.log; then
echo "Log present but no failure lines found in unittest.log."
if [ -f unittest.log ]; then
if ! grep -E "failed" unittest.log | grep -vE "^I[0-9]|^[0-9]+> (ERR:|FTL:)"; then
echo "unittest.log present but no failure lines found."
fi
elif [ -f build.log ]; then
# GCC/Clang emit "error:" (covers "fatal error:"); MSVC emits
# "error C####:", "error LNK####:", and "fatal error LNK####:".
# -A6 prints the lines that follow each match (source line, caret,
# notes, and the "N errors generated" tally) to capture the whole
# diagnostic block.
if ! grep -E -A6 "error:|error C[0-9]{4}|error LNK[0-9]{4}|fatal error" build.log; then
echo "build.log present but no compile errors found."
fi
else
echo "unittest.log/build.log not found; something went wrong."
exit 1
fi
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}

View File

@@ -3,6 +3,7 @@
#include <test/jtx/Env.h>
#include <test/jtx/TestHelpers.h>
#include <test/jtx/amount.h>
#include <test/jtx/envconfig.h>
#include <test/jtx/fee.h>
#include <test/jtx/mpt.h>
#include <test/jtx/pay.h>
@@ -101,6 +102,12 @@ class Invariants_test : public beast::unit_test::Suite
return xrpl::test::jtx::testableAmendments() | fixCleanup3_1_3 | fixCleanup3_2_0;
}
test::jtx::Env
makeEnv(FeatureBitset features)
{
return {*this, test::jtx::envconfig(), features, nullptr, beast::Severity::Disabled};
}
/**
* Run a specific test case to put the ledger into a state that will be
* detected by an invariant. Simulates the actions of a transaction that
@@ -130,7 +137,7 @@ class Invariants_test : public beast::unit_test::Suite
TxAccount setTxAccount = TxAccount::None)
{
doInvariantCheck(
test::jtx::Env(*this, defaultAmendments()),
makeEnv(defaultAmendments()),
expectLogs,
precheck,
fee,
@@ -1494,7 +1501,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain" + std::string(fixEnabled ? " fix" : "");
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain with no rules."}},
[](Account const& a1, Account const& a2, ApplyContext& ac) {
return createPermissionedDomain(ac, a1, a2, 0).get();
@@ -1507,7 +1514,7 @@ class Invariants_test : public beast::unit_test::Suite
static constexpr auto kTooBig = kMaxPermissionedDomainCredentialsArraySize + 1;
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain bad credentials size " + std::to_string(kTooBig)}},
[](Account const& a1, Account const& a2, ApplyContext& ac) {
return !!createPermissionedDomain(ac, a1, a2, kTooBig);
@@ -1518,7 +1525,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain 3";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain credentials aren't sorted"}},
[](Account const& a1, Account const& a2, ApplyContext& ac) {
auto slePd = createPermissionedDomain(ac, a1, a2, 0);
@@ -1542,7 +1549,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain 4";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain credentials aren't unique"}},
[](Account const& a1, Account const& a2, ApplyContext& ac) {
auto slePd = createPermissionedDomain(ac, a1, a2, 0);
@@ -1565,7 +1572,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain Set 1";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain with no rules."}},
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
// create PD
@@ -1586,7 +1593,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain Set 2";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain bad credentials size " + std::to_string(kTooBig)}},
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
// create PD
@@ -1617,7 +1624,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain Set 3";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain credentials aren't sorted"}},
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
// create PD
@@ -1647,7 +1654,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDomain Set 4";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"permissioned domain credentials aren't unique"}},
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
// create PD
@@ -1688,7 +1695,7 @@ class Invariants_test : public beast::unit_test::Suite
{
testcase << "PermissionedDomain set 2 domains ";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? badMoreThan1 : emptyV,
[](Account const& a1, Account const& a2, ApplyContext& ac) {
createPermissionedDomain(ac, a1, a2);
@@ -1734,7 +1741,7 @@ class Invariants_test : public beast::unit_test::Suite
{
testcase << "PermissionedDomain set 0 domains ";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? badNoDomains : emptyV,
[](Account const&, Account const&, ApplyContext&) { return true; },
XRPAmount{},
@@ -1757,7 +1764,7 @@ class Invariants_test : public beast::unit_test::Suite
env1.close();
doInvariantCheck(
Env(*this, features),
makeEnv(features),
a1,
a2,
fixEnabled ? badNoDomains : emptyV,
@@ -1798,7 +1805,7 @@ class Invariants_test : public beast::unit_test::Suite
{
testcase << "PermissionedDomain del, create domain ";
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? badNotDeleted : emptyV,
[](Account const& a1, Account const& a2, ApplyContext& ac) {
createPermissionedDomain(ac, a1, a2);
@@ -1995,7 +2002,7 @@ class Invariants_test : public beast::unit_test::Suite
testcase << "PermissionedDEX" + std::string(fixEnabled ? " fix" : "");
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"domain doesn't exist"}},
[](Account const& a1, Account const&, ApplyContext& ac) {
Keylet const offerKey = keylet::offer(a1.id(), 10);
@@ -2022,7 +2029,7 @@ class Invariants_test : public beast::unit_test::Suite
// missing domain ID in offer object
doInvariantCheck(
Env(*this, features),
makeEnv(features),
{{"hybrid offer is malformed"}},
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
Keylet const offerKey = keylet::offer(a2.id(), 10);
@@ -4342,7 +4349,7 @@ class Invariants_test : public beast::unit_test::Suite
};
doInvariantCheck(
Env{*this, defaultAmendments() - fixCleanup3_2_0},
makeEnv(defaultAmendments() - fixCleanup3_2_0),
{},
[](Account const&, Account const&, ApplyContext&) { return true; },
XRPAmount{},
@@ -5468,7 +5475,7 @@ class Invariants_test : public beast::unit_test::Suite
// sfHighLimit issue, not the keylet currency).
testcase << "overwrite: NoXRPTrustLines" + std::string(fixEnabled ? " fix" : "");
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? std::vector<std::string>{{"an XRP trust line was created"}}
: std::vector<std::string>{},
[&insertOrderedTrustLinePair](Account const& a1, Account const& a2, ApplyContext& ac) {
@@ -5496,7 +5503,7 @@ class Invariants_test : public beast::unit_test::Suite
// Regression: bad deep-freeze trust line followed by a valid one.
testcase << "overwrite: NoDeepFreeze" + std::string(fixEnabled ? " fix" : "");
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? std::vector<std::string>{{"a trust line with deep freeze flag without "
"normal freeze was created"}}
: std::vector<std::string>{},
@@ -5530,7 +5537,7 @@ class Invariants_test : public beast::unit_test::Suite
// still fires ("a MPT issuance was created").
testcase << "overwrite: NoZeroEscrow MPT" + std::string(fixEnabled ? " fix" : "");
doInvariantCheck(
Env(*this, features),
makeEnv(features),
fixEnabled ? std::vector<std::string>{{"escrow specifies invalid amount"}}
: std::vector<std::string>{{"a MPT issuance was created"}},
[](Account const& a1, Account const&, ApplyContext& ac) {