const assert = require('node:assert/strict'); const { execFile } = require('node:child_process'); const { createServer } = require('node:http'); const path = require('node:path'); const { test } = require('node:test'); const { evaluatePerformanceGates, parseArgs } = require('./load-test'); const passingSummary = { requestsPerSecond: 250.25, successRate: 99.95, latencyMs: { p95: 120.5, p99: 180.75 }, }; test('parseArgs reads all optional performance gates', () => { const options = parseArgs([ '--min-success-rate', '99.9', '--min-rps', '200', '--max-p95', '150', '--max-p99', '250', ]); assert.deepEqual(options.gates, { minSuccessRate: 99.9, minRequestsPerSecond: 200, maxP95Ms: 150, maxP99Ms: 250, }); }); test('parseArgs rejects invalid gate values', () => { assert.throws( () => parseArgs(['--min-success-rate', '100.1']), /min-success-rate must be a finite number between 0 and 100/, ); assert.throws(() => parseArgs(['--min-rps', '-1']), /min-rps must be a finite number/); assert.throws(() => parseArgs(['--max-p95']), /--max-p95 requires a value/); }); test('evaluatePerformanceGates passes when every threshold is satisfied', () => { const result = evaluatePerformanceGates(passingSummary, { minSuccessRate: 99.9, minRequestsPerSecond: 200, maxP95Ms: 150, maxP99Ms: 200, }); assert.equal(result.configured, true); assert.equal(result.passed, true); assert.equal(result.checks.length, 4); assert.ok(result.checks.every((check) => check.passed)); }); test('evaluatePerformanceGates reports every failed threshold', () => { const result = evaluatePerformanceGates(passingSummary, { minSuccessRate: 100, minRequestsPerSecond: 300, maxP95Ms: 100, maxP99Ms: 150, }); assert.equal(result.passed, false); assert.deepEqual( result.checks.filter((check) => !check.passed).map((check) => check.metric), ['successRate', 'requestsPerSecond', 'latencyMs.p95', 'latencyMs.p99'], ); }); test('load-test process exits with code 2 and a clear report when a gate fails', async () => { const server = createServer((_request, response) => { response.statusCode = 503; response.end('unavailable'); }); await new Promise((resolve, reject) => { server.once('error', reject); server.listen(0, '127.0.0.1', resolve); }); try { const address = server.address(); assert.ok(address && typeof address === 'object'); const result = await runLoadTest([ '--url', `http://127.0.0.1:${address.port}`, '--duration', '0.05', '--concurrency', '1', '--warmup', '0', '--min-success-rate', '100', ]); assert.equal(result.exitCode, 2); assert.match(result.stdout, /Performance gates: FAILED \(0\/1\)/); assert.match(result.stdout, /\[FAIL\] Success rate:/); } finally { await new Promise((resolve, reject) => { server.close((error) => (error ? reject(error) : resolve())); }); } }); function runLoadTest(args) { const scriptPath = path.join(__dirname, 'load-test.js'); return new Promise((resolve) => { execFile(process.execPath, [scriptPath, ...args], (error, stdout, stderr) => { resolve({ exitCode: error && typeof error.code === 'number' ? error.code : 0, stdout, stderr, }); }); }); }