Skip to content

Commit b60b999

Browse files
committed
Test AI-reworked tx test runner to bundle test cases in batches to avoid CI overload/timeout
1 parent 611ec5b commit b60b999

File tree

1 file changed

+101
-48
lines changed

1 file changed

+101
-48
lines changed

packages/tx/test/transactionRunner.spec.ts

Lines changed: 101 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -55,59 +55,112 @@ const EIPs: Record<string, number[] | undefined> = {
5555

5656
describe('TransactionTests', async () => {
5757
const fileFilterRegex = file !== undefined ? new RegExp(file + '[^\\w]') : undefined
58-
await getTests(
59-
(
60-
_filename: string,
61-
subDir: string,
62-
testName: string,
63-
testData: OfficialTransactionTestData,
64-
) => {
65-
for (const forkName of forkNames) {
66-
if (testData.result[forkName] === undefined) {
67-
continue
68-
}
69-
it(`${testName} - [${forkName}]`, () => {
70-
const forkTestData = testData.result[forkName]
71-
const shouldBeInvalid = forkTestData.exception !== undefined
72-
73-
const rawTx = hexToBytes(testData.txbytes as PrefixedHexString)
74-
const hardfork = forkNameMap[forkName]
75-
const common = new Common({ chain: Mainnet, hardfork })
76-
const activateEIPs = EIPs[forkName]
77-
if (activateEIPs !== undefined) {
78-
common.setEIPs(activateEIPs)
79-
}
8058

81-
let tx
82-
let sender
83-
let hash
84-
let isValid
85-
try {
86-
tx = createTxFromRLP(rawTx, { common })
87-
sender = tx.getSenderAddress().toString()
88-
hash = bytesToHex(tx.hash())
89-
if (!tx.isValid()) {
90-
throw EthereumJSErrorWithoutCode('Tx is invalid')
91-
}
92-
isValid = true
93-
} catch {
94-
if (!shouldBeInvalid) {
95-
assert.fail('Tx creation threw an error, but should be valid')
96-
}
97-
// Tx is correctly marked as "invalid", so test has passed
98-
return
99-
}
59+
// Collect all test data first to batch tests more efficiently
60+
const testDataCollection: Array<{
61+
filename: string
62+
subDir: string
63+
testName: string
64+
testData: OfficialTransactionTestData
65+
}> = []
10066

101-
const senderIsCorrect = forkTestData.sender === sender
102-
const hashIsCorrect = forkTestData.hash === hash
103-
assert.isTrue(isValid, 'tx is valid')
104-
assert.isTrue(senderIsCorrect, 'sender is correct')
105-
assert.isTrue(hashIsCorrect, 'hash is correct')
106-
}, 120000)
107-
}
67+
await getTests(
68+
(filename: string, subDir: string, testName: string, testData: OfficialTransactionTestData) => {
69+
testDataCollection.push({ filename, subDir, testName, testData })
10870
},
10971
fileFilterRegex,
11072
undefined,
11173
'TransactionTests',
11274
)
75+
76+
// Process tests in batches to reduce worker load
77+
const BATCH_SIZE = 50
78+
for (let i = 0; i < testDataCollection.length; i += BATCH_SIZE) {
79+
const batch = testDataCollection.slice(i, i + BATCH_SIZE)
80+
81+
describe(`Batch ${Math.floor(i / BATCH_SIZE) + 1}`, () => {
82+
for (const { testName, testData } of batch) {
83+
// Group tests by test name to reduce individual test count
84+
it(`${testName}`, () => {
85+
const results: Array<{ fork: string; passed: boolean; error?: string }> = []
86+
87+
for (const forkName of forkNames) {
88+
if (testData.result[forkName] === undefined) {
89+
continue
90+
}
91+
92+
try {
93+
const forkTestData = testData.result[forkName]
94+
const shouldBeInvalid = forkTestData.exception !== undefined
95+
96+
const rawTx = hexToBytes(testData.txbytes as PrefixedHexString)
97+
const hardfork = forkNameMap[forkName]
98+
const common = new Common({ chain: Mainnet, hardfork })
99+
const activateEIPs = EIPs[forkName]
100+
if (activateEIPs !== undefined) {
101+
common.setEIPs(activateEIPs)
102+
}
103+
104+
let tx
105+
let sender
106+
let hash
107+
let isValid
108+
try {
109+
tx = createTxFromRLP(rawTx, { common })
110+
sender = tx.getSenderAddress().toString()
111+
hash = bytesToHex(tx.hash())
112+
if (!tx.isValid()) {
113+
throw EthereumJSErrorWithoutCode('Tx is invalid')
114+
}
115+
isValid = true
116+
} catch {
117+
if (!shouldBeInvalid) {
118+
results.push({
119+
fork: forkName,
120+
passed: false,
121+
error: 'Tx creation threw an error, but should be valid',
122+
})
123+
continue
124+
}
125+
// Tx is correctly marked as "invalid", so test has passed
126+
results.push({ fork: forkName, passed: true })
127+
continue
128+
}
129+
130+
const senderIsCorrect = forkTestData.sender === sender
131+
const hashIsCorrect = forkTestData.hash === hash
132+
133+
if (!isValid) {
134+
results.push({ fork: forkName, passed: false, error: 'tx is not valid' })
135+
continue
136+
}
137+
if (!senderIsCorrect) {
138+
results.push({ fork: forkName, passed: false, error: 'sender is not correct' })
139+
continue
140+
}
141+
if (!hashIsCorrect) {
142+
results.push({ fork: forkName, passed: false, error: 'hash is not correct' })
143+
continue
144+
}
145+
146+
results.push({ fork: forkName, passed: true })
147+
} catch (error) {
148+
results.push({
149+
fork: forkName,
150+
passed: false,
151+
error: error instanceof Error ? error.message : String(error),
152+
})
153+
}
154+
}
155+
156+
// Check if all fork tests passed
157+
const failedResults = results.filter((r) => !r.passed)
158+
if (failedResults.length > 0) {
159+
const errorMessages = failedResults.map((r) => `${r.fork}: ${r.error}`).join('; ')
160+
assert.fail(`Test failed for forks: ${errorMessages}`)
161+
}
162+
}, 300000) // Increased timeout for batched tests
163+
}
164+
})
165+
}
113166
})

0 commit comments

Comments
 (0)