Files
baiyue-firstleg/scripts/ci-maven-resource-contract.test.mjs

68 lines
3.9 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync, mkdtempSync, writeFileSync, rmSync, existsSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { spawnSync } from 'node:child_process'
const root = fileURLToPath(new URL('..', import.meta.url))
const wrapper = resolve(root, 'deploy/scripts/run-ci-maven.sh')
const bash = process.platform === 'win32' ? 'C:/Program Files/Git/bin/bash.exe' : 'bash'
const shellAvailable = process.platform !== 'win32' || existsSync(bash)
test('both Jenkins Maven paths share one cross-job lock and bounded host entry', () => {
for (const file of ['Jenkinsfile', 'Jenkinsfile.service']) {
const source = readFileSync(resolve(root, file), 'utf8')
assert.match(source, /lock\(resource: 'firstleg-test-maven'\)\s*\{\s*timeout\(time: 50, unit: 'MINUTES'\)/)
assert.match(source, /sh deploy\/scripts\/run-ci-maven\.sh --settings/)
assert.doesNotMatch(source, /(?:^|\n)\s*mvn\s|sh "mvn /)
}
const source = readFileSync(wrapper, 'utf8')
assert.match(source, /exec 9>/)
assert.match(source, /flock -n 9/)
assert.match(source, /exec timeout --signal=TERM --kill-after=30s 45m mvn -Pci-bounded/)
assert.doesNotMatch(source, /exec timeout[^\n]*--foreground/)
})
test('test JVM gets a separate heap, JaCoCo late binding, and parent-loss cleanup', () => {
const pom = readFileSync(resolve(root, 'pom.xml'), 'utf8')
const profile = pom.match(/<profile>\s*<id>ci-bounded<\/id>([\s\S]*?)<\/profile>/)?.[1]
assert.ok(profile)
assert.match(profile, /<argLine>@\{argLine\}[^<]*-Xmx1024m[^<]*-XX:\+ExitOnOutOfMemoryError<\/argLine>/)
for (const [name, value] of Object.entries({ forkCount: '1', enableProcessChecker: 'ping', shutdown: 'kill',
forkedProcessTimeoutInSeconds: '1200', forkedProcessExitTimeoutInSeconds: '30' }))
assert.ok(profile.includes(`<${name}>${value}</${name}>`))
})
test('shell rejects parallel reactors and held host lock before invoking Maven; propagates failure', { skip: !shellAvailable }, () => {
const directory = mkdtempSync(join(tmpdir(), 'ci-maven-command-test-'))
try {
// Stand-ins exercise command wiring, not Linux flock or process-group signalling.
writeFileSync(join(directory, 'flock'), '#!/bin/sh\nexit "${TEST_LOCK_STATUS:-0}"\n', { mode: 0o755 })
writeFileSync(join(directory, 'mvn'), '#!/bin/sh\nexit 99\n', { mode: 0o755 })
writeFileSync(join(directory, 'timeout'), '#!/bin/sh\nprintf "%s\\n" "$MAVEN_OPTS" "$@"\nexit "${TEST_CHILD_STATUS:-0}"\n', { mode: 0o755 })
const run = (args, extra = {}) => spawnSync(bash, ['-c',
'testbin=$(cd "$1" && pwd); shift; PATH="$testbin:$PATH"; export PATH; exec sh "$@"',
'fixture', directory.replaceAll('\\', '/'), wrapper.replaceAll('\\', '/'), ...args],
{ encoding: 'utf8', timeout: 10000, env: { ...process.env, ...extra } })
for (const args of [['-T', '3', 'test'], ['-T3', 'test'], ['--threads=3', 'test']]) {
const result = run(args)
assert.equal(result.status, 64, result.stderr)
assert.equal(result.stdout, '')
}
const held = run(['test'], { TEST_LOCK_STATUS: '1' })
assert.equal(held.status, 75, held.stderr)
assert.equal(held.stdout, '')
const normal = run(['-pl', 'file', '-am', 'test'], { TEST_CHILD_STATUS: '23', MAVEN_OPTS: '-Xmx8g' })
assert.equal(normal.status, 23, normal.stderr)
assert.match(normal.stdout, /-Xmx768m/)
assert.doesNotMatch(normal.stdout, /-Xmx8g/)
assert.match(normal.stdout, /--signal=TERM\r?\n--kill-after=30s\r?\n45m\r?\nmvn\r?\n-Pci-bounded\r?\n-pl\r?\nfile/)
} finally {
// Only this newly-created fixture directory; no project copies or shared caches removed.
assert.equal(resolve(directory).startsWith(resolve(tmpdir()) + (process.platform === 'win32' ? '\\' : '/')), true)
rmSync(directory, { recursive: true })
}
})