From 64dd135882a824758208f0dea16e7bc5f6072df6 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 21 Aug 2026 12:09:52 +0300 Subject: [PATCH] =?UTF-8?q?fix(tests):=20verify-snapshots=20=E2=80=94=20?= =?UTF-8?q?=D0=B3=D0=B5=D0=B9=D1=82=20=D0=BF=D0=BE=20=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D1=81=D0=B8=D0=B8=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B0?= =?UTF-8?q?,=20=D0=B0=20=D0=BD=D0=B5=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=BE=20=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пропуск кейса решался только режимом совместимости. Кейс на формате 2.21 с совместимостью 8.3.27 на платформе 8.3.24 пропускался, а на 8.3.27 доходил до загрузки и падал: формат 2.21 требует 8.5. На стендах с промежуточной платформой (в том числе macOS с 8.3.27) это давало постоянный ложный красный. Эталон соответствия «формат → платформа» — таблица «Лестница версий» из docs/1c-configuration-spec.md, как и в check-format-versions.mjs. Co-Authored-By: Claude Opus 5 --- tests/skills/verify-snapshots.mjs | 42 ++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/skills/verify-snapshots.mjs b/tests/skills/verify-snapshots.mjs index e5ac1463e..b33be157b 100644 --- a/tests/skills/verify-snapshots.mjs +++ b/tests/skills/verify-snapshots.mjs @@ -730,6 +730,45 @@ function compatibilityGap(configDir, v8path) { return null; } +// Версия формата выгрузки против платформы: формат 2.21 не загрузится на 8.3.27, даже если +// режим совместимости платформе подходит. Без этой проверки кейс на 2.21 скипался только на +// 8.3.24 (по совместимости), а на 8.3.27 доходил до загрузки и падал — постоянный ложный +// красный на стендах с промежуточной платформой. +// +// Эталон — таблица «Лестница версий» из docs/1c-configuration-spec.md (§7.1); разбор — копия +// такого же в check-format-versions.mjs, держать одинаковыми. +function formatGap(configDir, v8path) { + const cfgFile = join(configDir, 'Configuration.xml'); + if (!existsSync(cfgFile)) return null; + const fm = /]*\sversion="(\d+\.\d+)"/.exec(readFileSync(cfgFile, 'utf8')); + const pm = /(\d+\.\d+\.\d+)/.exec(v8path || ''); + if (!fm || !pm) return null; + + const specFile = join(REPO_ROOT, 'docs', '1c-configuration-spec.md'); + if (!existsSync(specFile)) return null; + const section = readFileSync(specFile, 'utf8').split(/^### 7\.1\./m)[1]; + if (!section) return null; + const ladder = new Map(); // версия формата → минимальная платформа + for (const line of section.split(/^###? /m)[0].split('\n')) { + const m = /^\|\s*([\d.]+)\s*\|\s*`?(\d+\.\d+)`?\s*\|/.exec(line); + if (m) ladder.set(m[2], m[1]); + } + const needPlatform = ladder.get(fm[1]); + if (!needPlatform) return null; + + const cmp = (a, b) => { + const x = a.split('.').map(Number), y = b.split('.').map(Number); + for (let i = 0; i < Math.max(x.length, y.length); i++) { + if ((x[i] || 0) !== (y[i] || 0)) return (x[i] || 0) - (y[i] || 0); + } + return 0; + }; + if (cmp(pm[1], needPlatform) < 0) { + return `формат выгрузки ${fm[1]} требует платформу ${needPlatform}, доступна ${pm[1]} — запустите с --v8path`; + } + return null; +} + // Аргументы cf-init для вариантов пустой конфигурации. Копия таблицы EMPTY_CONFIGS из // runner.mjs — держать одинаковыми: разойдутся, и верификация пойдёт не на том формате, // на котором прогонялся кейс. @@ -1001,7 +1040,8 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) { // стенда, а не дефект кейса, поэтому пропускаем с причиной: иначе на машине без нужной // платформы кейсы с гейтом по версии формата давали бы ложное падение. if (opts.v8ctx && configDir) { - const compatSkip = compatibilityGap(configDir, opts.v8ctx.v8path); + const compatSkip = compatibilityGap(configDir, opts.v8ctx.v8path) + || formatGap(configDir, opts.v8ctx.v8path); if (compatSkip) { result.skipped = true; result.skipReason = compatSkip;