Skip to content

Commit 9b6e0ac

Browse files
committed
We got explicit resource managment at home
1 parent 2ecbdbf commit 9b6e0ac

File tree

1 file changed

+109
-109
lines changed

1 file changed

+109
-109
lines changed

run-tests.js

Lines changed: 109 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -505,15 +505,7 @@ ${ENDGROUP}`)
505505
const testSignal = testController.signal
506506
let hadFailures = false
507507

508-
async function yourTurn() {
509-
await sema.acquire()
510-
if (testSignal.aborted) {
511-
sema.release()
512-
throw testSignal.reason
513-
}
514-
}
515-
516-
const runTest = (/** @type {TestFile} */ test, isFinalRun, isRetry) =>
508+
const runTestOnce = (/** @type {TestFile} */ test, isFinalRun, isRetry) =>
517509
new Promise((resolve, reject) => {
518510
const start = new Date().getTime()
519511
let outputChunks = []
@@ -691,6 +683,100 @@ ${ENDGROUP}`)
691683
})
692684
})
693685

686+
const runTest = async (/** @type {TestFile} */ test) => {
687+
let passed = false
688+
689+
const shouldSkipRetries = skipRetryTestManifest.find((t) =>
690+
t.includes(test.file)
691+
)
692+
const numRetries = shouldSkipRetries ? 0 : originalRetries
693+
if (shouldSkipRetries) {
694+
console.log(
695+
`Skipping retry for ${test.file} due to skipRetryTestManifest`
696+
)
697+
}
698+
699+
for (let i = 0; i < numRetries + 1; i++) {
700+
try {
701+
console.log(`Starting ${test.file} retry ${i}/${numRetries}`)
702+
const time = await runTestOnce(
703+
test,
704+
shouldSkipRetries || i === numRetries,
705+
shouldSkipRetries || i > 0
706+
)
707+
timings.push({
708+
file: test.file,
709+
time,
710+
})
711+
passed = true
712+
console.log(
713+
`${test.file} finished on retry ${i}/${numRetries} in ${time / 1000}s`
714+
)
715+
break
716+
} catch (err) {
717+
if (i < numRetries) {
718+
try {
719+
let testDir = path.dirname(path.join(__dirname, test.file))
720+
721+
// if test is nested in a test folder traverse up a dir to ensure
722+
// we clean up relevant test files
723+
if (testDir.endsWith('/test') || testDir.endsWith('\\test')) {
724+
testDir = path.join(testDir, '..')
725+
}
726+
console.log('Cleaning test files at', testDir)
727+
await exec(`git clean -fdx "${testDir}"`)
728+
await exec(`git checkout "${testDir}"`)
729+
} catch (err) {}
730+
} else {
731+
console.error(`${test.file} failed due to ${err}`)
732+
}
733+
}
734+
}
735+
736+
if (!passed) {
737+
hadFailures = true
738+
const error = new Error(
739+
`Test ${test.file} failed to pass within ${numRetries} retries`
740+
)
741+
742+
if (!shouldContinueTestsOnError) {
743+
testController.abort(error)
744+
} else {
745+
console.error(error)
746+
console.log(
747+
`CONTINUE_ON_ERROR enabled, continuing tests after ${test.file} failed`
748+
)
749+
}
750+
}
751+
752+
// Emit test output if test failed or if we're continuing tests on error
753+
// This is parsed by the commenter webhook to notify about failing tests
754+
if ((!passed || shouldContinueTestsOnError) && isTestJob) {
755+
try {
756+
const testsOutput = await fsp.readFile(
757+
`${test.file}${RESULTS_EXT}`,
758+
'utf8'
759+
)
760+
const obj = JSON.parse(testsOutput)
761+
obj.processEnv = {
762+
NEXT_TEST_MODE: process.env.NEXT_TEST_MODE,
763+
HEADLESS: process.env.HEADLESS,
764+
}
765+
await outputSema.acquire()
766+
if (GROUP) console.log(`${GROUP}Result as JSON for tooling`)
767+
console.log(
768+
`--test output start--`,
769+
JSON.stringify(obj),
770+
`--test output end--`
771+
)
772+
if (ENDGROUP) console.log(ENDGROUP)
773+
outputSema.release()
774+
} catch (err) {
775+
console.log(`Failed to load test output`, err)
776+
}
777+
}
778+
}
779+
694780
const directorySemas = new Map()
695781

696782
const originalRetries = numRetries
@@ -704,112 +790,26 @@ ${ENDGROUP}`)
704790
if (/^test[/\\]integration/.test(test.file) && dirSema === undefined) {
705791
directorySemas.set(dirName, (dirSema = new Sema(1)))
706792
}
793+
// TODO: Use explicit resource managment instead of this acquire/release pattern
794+
// once CI runs with Node.js 24+.
707795
if (dirSema) await dirSema.acquire()
708-
709-
try {
710-
await yourTurn()
711-
} catch (cause) {
712-
const error = new Error(`Skipped due to abort.`, { cause })
796+
await sema.acquire()
797+
if (testSignal.aborted) {
798+
const error = new Error(`Skipped due to abort.`, {
799+
cause: testSignal.reason,
800+
})
713801
error.name = test.file
802+
if (dirSema) dirSema.release()
803+
sema.release()
714804
throw error
715805
}
716806

717-
let passed = false
718-
719-
const shouldSkipRetries = skipRetryTestManifest.find((t) =>
720-
t.includes(test.file)
721-
)
722-
const numRetries = shouldSkipRetries ? 0 : originalRetries
723-
if (shouldSkipRetries) {
724-
console.log(
725-
`Skipping retry for ${test.file} due to skipRetryTestManifest`
726-
)
727-
}
728-
729-
for (let i = 0; i < numRetries + 1; i++) {
730-
try {
731-
console.log(`Starting ${test.file} retry ${i}/${numRetries}`)
732-
const time = await runTest(
733-
test,
734-
shouldSkipRetries || i === numRetries,
735-
shouldSkipRetries || i > 0
736-
)
737-
timings.push({
738-
file: test.file,
739-
time,
740-
})
741-
passed = true
742-
console.log(
743-
`${test.file} finished on retry ${i}/${numRetries} in ${
744-
time / 1000
745-
}s`
746-
)
747-
break
748-
} catch (err) {
749-
if (i < numRetries) {
750-
try {
751-
let testDir = path.dirname(path.join(__dirname, test.file))
752-
753-
// if test is nested in a test folder traverse up a dir to ensure
754-
// we clean up relevant test files
755-
if (testDir.endsWith('/test') || testDir.endsWith('\\test')) {
756-
testDir = path.join(testDir, '..')
757-
}
758-
console.log('Cleaning test files at', testDir)
759-
await exec(`git clean -fdx "${testDir}"`)
760-
await exec(`git checkout "${testDir}"`)
761-
} catch (err) {}
762-
} else {
763-
console.error(`${test.file} failed due to ${err}`)
764-
}
765-
}
766-
}
767-
768-
if (!passed) {
769-
hadFailures = true
770-
const error = new Error(
771-
`Test ${test.file} failed to pass within ${numRetries} retries`
772-
)
773-
774-
if (!shouldContinueTestsOnError) {
775-
testController.abort(error)
776-
} else {
777-
console.error(error)
778-
console.log(
779-
`CONTINUE_ON_ERROR enabled, continuing tests after ${test.file} failed`
780-
)
781-
}
782-
}
783-
784-
// Emit test output if test failed or if we're continuing tests on error
785-
// This is parsed by the commenter webhook to notify about failing tests
786-
if ((!passed || shouldContinueTestsOnError) && isTestJob) {
787-
try {
788-
const testsOutput = await fsp.readFile(
789-
`${test.file}${RESULTS_EXT}`,
790-
'utf8'
791-
)
792-
const obj = JSON.parse(testsOutput)
793-
obj.processEnv = {
794-
NEXT_TEST_MODE: process.env.NEXT_TEST_MODE,
795-
HEADLESS: process.env.HEADLESS,
796-
}
797-
await outputSema.acquire()
798-
if (GROUP) console.log(`${GROUP}Result as JSON for tooling`)
799-
console.log(
800-
`--test output start--`,
801-
JSON.stringify(obj),
802-
`--test output end--`
803-
)
804-
if (ENDGROUP) console.log(ENDGROUP)
805-
outputSema.release()
806-
} catch (err) {
807-
console.log(`Failed to load test output`, err)
808-
}
807+
try {
808+
await runTest(test)
809+
} finally {
810+
sema.release()
811+
if (dirSema) dirSema.release()
809812
}
810-
811-
sema.release()
812-
if (dirSema) dirSema.release()
813813
})
814814
)
815815

0 commit comments

Comments
 (0)