Files
brain/tools/mutate-runner.test.mjs

57 lines
3.4 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { classifyMutationResult, runMutationForFile } from './mutate-runner.mjs';
import { mkdtempSync, writeFileSync, readFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
describe('classifyMutationResult (чистая классификация P18)', () => {
it('baseline не зелёный → killed:false reason baseline-not-green', () => {
expect(classifyMutationResult({ baselineGreen: false, mutantOutcomes: [] }))
.toEqual({ mutationKilled: false, reason: 'baseline-not-green' });
});
it('нет валидных мутантов (все loadError) → no-valid-mutants', () => {
expect(classifyMutationResult({ baselineGreen: true, mutantOutcomes: [{ allGreen: false, loadError: true }] }))
.toEqual({ mutationKilled: false, reason: 'no-valid-mutants' });
});
it('хоть один валидный мутант покраснел (allGreen:false, не loadError) → killed', () => {
expect(classifyMutationResult({ baselineGreen: true, mutantOutcomes: [
{ allGreen: true, loadError: false }, { allGreen: false, loadError: false } ] }))
.toEqual({ mutationKilled: true, reason: 'ok' });
});
it('все валидные мутанты выжили (тест ничего не проверяет) → mutation-survived', () => {
expect(classifyMutationResult({ baselineGreen: true, mutantOutcomes: [{ allGreen: true, loadError: false }] }))
.toEqual({ mutationKilled: false, reason: 'mutation-survived' });
});
});
describe('runMutationForFile (in-place + восстановление SE-LB-3)', () => {
it('восстанавливает оригинал файла после прогона (даже если мутант валит тест)', () => {
const dir = mkdtempSync(join(tmpdir(), 'mut-'));
const file = join(dir, 'x.mjs');
const original = 'export const f = (a, b) => a === b;\n';
writeFileSync(file, original);
// Фейковый runTest: baseline зелёный; на мутированном содержимом (=== заменён) — красный.
const runTest = () => {
const cur = readFileSync(file, 'utf-8');
const baseline = cur === original;
return { allGreen: baseline, numPassed: baseline ? 1 : 0, numFailed: baseline ? 0 : 1, loadError: false };
};
const res = runMutationForFile({ filePath: file, generate: (s) => [{ label: 'm', mutated: s.replace('===', '!==') }], runTest });
expect(res.baselineGreen).toBe(true);
expect(res.mutantOutcomes.some((o) => o.allGreen === false)).toBe(true);
expect(readFileSync(file, 'utf-8')).toBe(original); // восстановлен
rmSync(dir, { recursive: true, force: true });
});
it('baseline красный → мутацию не запускает, baselineGreen:false, файл цел', () => {
const dir = mkdtempSync(join(tmpdir(), 'mut-'));
const file = join(dir, 'y.mjs');
writeFileSync(file, 'broken');
const runTest = () => ({ allGreen: false, numPassed: 0, numFailed: 1, loadError: false });
const res = runMutationForFile({ filePath: file, generate: () => [{ label: 'm', mutated: 'mutant' }], runTest });
expect(res.baselineGreen).toBe(false);
expect(res.mutantOutcomes).toEqual([]);
expect(readFileSync(file, 'utf-8')).toBe('broken');
rmSync(dir, { recursive: true, force: true });
});
});