397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
4.2 KiB
JavaScript
64 lines
4.2 KiB
JavaScript
// tools/criterion-green.test.mjs
|
|
// 5.6 (Машина 5 Пакет 5, Блок 3): по-критерийный производитель GREEN. Эмитит подписанный
|
|
// подписантом green ТОЛЬКО при настоящем зелёном прогоне — мутация P18 как условие (сломал
|
|
// изменённый код → тест обязан покраснеть; выжил → не проверяет → не green). code_fingerprint
|
|
// (Δ2) детерминирован над содержимым изменённых файлов + тестов. Интеграция с критерий-гейтом
|
|
// из judge-orchestrator (5.5): произведённый green проходит все 4 шага на свежем отпечатке.
|
|
import { describe, it, expect } from 'vitest';
|
|
import { codeFingerprint, produceGreen } from './criterion-green.mjs';
|
|
import { verifyGreen } from './floor-signer.mjs';
|
|
import { runCriterionGate } from './judge-orchestrator.mjs';
|
|
|
|
const SK = 'producer-signer-key';
|
|
|
|
describe('codeFingerprint (5.6, Δ2): детерминированный отпечаток изменённых файлов', () => {
|
|
it('детерминирован над одним содержимым, порядок ключей не важен', () => {
|
|
const a = codeFingerprint({ 'a.mjs': 'x', 'a.test.mjs': 'y' });
|
|
const b = codeFingerprint({ 'a.test.mjs': 'y', 'a.mjs': 'x' });
|
|
expect(a).toBe(b);
|
|
expect(a).toMatch(/^[0-9a-f]{64}$/);
|
|
});
|
|
it('правка содержимого файла → другой отпечаток (green аннулируется)', () => {
|
|
expect(codeFingerprint({ 'a.mjs': 'x' })).not.toBe(codeFingerprint({ 'a.mjs': 'x2' }));
|
|
});
|
|
});
|
|
|
|
describe('produceGreen (5.6): подписанный по-критерийный GREEN; мутация P18 — условие настоящего green', () => {
|
|
it('тест прошёл И мутация убита И ключ → green:true + валидная подпись подписанта', () => {
|
|
const fp = codeFingerprint({ 'a.mjs': 'code', 'a.test.mjs': 'test' });
|
|
const rec = produceGreen({ criterion_id: 'c1', occurrence: 1, code_fingerprint: fp, coverage_of_changed: 1, testPassed: true, mutationKilled: true, signerKey: SK });
|
|
expect(rec.green).toBe(true);
|
|
expect(rec.code_fingerprint).toBe(fp);
|
|
expect(rec.coverage_of_changed).toBe(1);
|
|
expect(verifyGreen({ criterion_id: rec.criterion_id, code_fingerprint: rec.code_fingerprint, occurrence: rec.occurrence, sig: rec.sig }, SK)).toBe(true);
|
|
});
|
|
it('P18: мутация ВЫЖИЛА (тест не проверяет) → green:false, нет подписи', () => {
|
|
const rec = produceGreen({ criterion_id: 'c1', occurrence: 1, code_fingerprint: 'fp', testPassed: true, mutationKilled: false, signerKey: SK });
|
|
expect(rec.green).toBe(false);
|
|
expect(rec.reason).toBe('mutation-survived');
|
|
expect(rec.sig).toBeUndefined();
|
|
});
|
|
it('тест не прошёл → green:false', () => {
|
|
const rec = produceGreen({ criterion_id: 'c1', occurrence: 1, code_fingerprint: 'fp', testPassed: false, mutationKilled: true, signerKey: SK });
|
|
expect(rec.green).toBe(false);
|
|
expect(rec.reason).toBe('test-not-passed');
|
|
});
|
|
it('настоящий green, но нет ключа подписанта → green:false (fail-CLOSE)', () => {
|
|
const rec = produceGreen({ criterion_id: 'c1', occurrence: 1, code_fingerprint: 'fp', testPassed: true, mutationKilled: true, signerKey: undefined });
|
|
expect(rec.green).toBe(false);
|
|
expect(rec.reason).toBe('no-signer-key');
|
|
});
|
|
it('произведённый green проходит весь критерий-гейт (5.5) на свежем отпечатке', () => {
|
|
const fp = codeFingerprint({ 'a.mjs': 'code' });
|
|
const rec = produceGreen({ criterion_id: 'c1', occurrence: 1, code_fingerprint: fp, testPassed: true, mutationKilled: true, signerKey: SK });
|
|
const gate = runCriterionGate({
|
|
criteria: [{ id: 'c1' }],
|
|
greenRuns: [rec],
|
|
sealedCriterionIds: ['c1'],
|
|
currentFingerprints: { c1: fp },
|
|
signerKey: SK,
|
|
});
|
|
expect(gate.passed).toBe(true);
|
|
});
|
|
});
|