From 7b40eb4c0bdb0ae8333699d1351243ac581e3ad2 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 22 Aug 2026 12:34:45 +0300 Subject: [PATCH] =?UTF-8?q?fix(meta-validate):=20=D1=81=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8,=20=D0=B0=20=D0=BD=D0=B5=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D1=87=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=B0,=20=D1=80=D0=B5=D1=88=D0=B0=D0=B5=D1=82=20=D1=83=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D0=BD=D1=8C=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA?= =?UTF-8?q?=D0=B8=20(#84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проверки 16 и 20 выбирали уровень по наличию файла, тогда как платформа судит по составу конфигурации. Из-за этого валидатор ошибался в обе стороны: пропускал ссылку на форму объекта, которого в конфигурации нет (WARN, exit=0 — платформа такую выгрузку не грузит), и ложно отказывал на фрагменте частичной выгрузки, где файла формы нет намеренно. Единое правило: ChildObjects отвечает за существование объекта, наличие файла — только за полноту выгрузки. Нет в составе -> ERROR, в составе есть, а файла нет -> WARN. Уровень для фрагмента остаётся мягким сознательно: один и тот же фрагмент грузится или нет в зависимости от состояния конфигурации БД, которого валидатору не видно. Матрица снята на платформе 8.3.24.1691 (полная и частичная загрузка, семь ситуаций). Прогноз про загрузку убран из текста WARN — там он не гарантирован. Состав читается поиском подстроки в границах секции ChildObjects, без разбора XML: batch-режим порождает процесс на объект, и полная карта оплачивалась бы каждым объектом. Корпусный прогон по acc_8.3.24 и erp_8.3.24 (33 895 объектов): расхождений до/после нет. Co-Authored-By: Claude Opus 5 (1M context) --- .../meta-validate/scripts/meta-validate.ps1 | 146 ++++++++-- .../meta-validate/scripts/meta-validate.py | 159 ++++++++--- .../error-commonform-absent.json | 9 + .../error-default-form-file-missing.json | 9 - .../error-default-form-foreign-absent.json | 9 + .../error-form-file-missing-full-tree.json | 9 + ...missing.json => error-reftype-absent.json} | 5 +- .../Catalogs/Товары.xml | 93 +++++++ .../Configuration.xml | 253 ++++++++++++++++++ .../Catalogs/Товары.xml | 93 +++++++ .../Configuration.xml | 253 ++++++++++++++++++ .../Catalogs/Товары.xml | 93 +++++++ .../Configuration.xml | 253 ++++++++++++++++++ .../Catalogs/Товары.xml | 93 +++++++ .../Configuration.xml | 253 ++++++++++++++++++ .../Catalogs/Товары.xml | 93 +++++++ .../Catalogs/Товары/Ext/ObjectModule.bsl | 1 + .../Configuration.xml | 253 ++++++++++++++++++ .../Catalogs/Товары.xml | 133 +++++++++ .../Configuration.xml | 253 ++++++++++++++++++ .../warn-commonform-not-dumped.json | 13 + .../warn-default-form-foreign-not-dumped.json | 13 + .../warn-form-file-missing-fragment.json | 13 + .../warn-reftype-not-dumped.json | 13 + 24 files changed, 2442 insertions(+), 73 deletions(-) create mode 100644 tests/skills/cases/meta-validate/error-commonform-absent.json delete mode 100644 tests/skills/cases/meta-validate/error-default-form-file-missing.json create mode 100644 tests/skills/cases/meta-validate/error-default-form-foreign-absent.json create mode 100644 tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json rename tests/skills/cases/meta-validate/{warn-reftype-missing.json => error-reftype-absent.json} (72%) create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml create mode 100644 tests/skills/cases/meta-validate/warn-commonform-not-dumped.json create mode 100644 tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json create mode 100644 tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json create mode 100644 tests/skills/cases/meta-validate/warn-reftype-not-dumped.json diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1 index aaab22215..7d86b8967 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.ps1 +++ b/.claude/skills/meta-validate/scripts/meta-validate.ps1 @@ -1,4 +1,4 @@ -# meta-validate v1.21 — Validate 1C metadata object structure +# meta-validate v1.22 — Validate 1C metadata object structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills [CmdletBinding(PositionalBinding=$false)] param( @@ -1466,17 +1466,69 @@ if ($childObjNode) { } } +# --- Состав конфигурации (ChildObjects из Configuration.xml) --- +# Платформа судит о существовании объекта по СОСТАВУ, а не по наличию файла. Файла может не быть +# в частичной выгрузке: такой фрагмент грузится через /LoadConfigFromFiles -listFile слиянием с базой, +# и ссылка на невыгруженный объект остаётся рабочей. Отсюда два разных исхода: +# нет в составе -> платформа отвергнет загрузку всегда -> ERROR +# в составе, файла нет -> полная загрузка упадёт, частичная пройдёт -> WARN +# ChildObjects конфигурации — плоский список <Вид>Имя, поэтому ищем подстроку в границах секции +# без копирования и без разбора XML: batch-режим порождает процесс на объект, и полная карта (~100 мс) +# оплачивалась бы каждым объектом. + +$script:cfgText = $null +$script:cfgChildStart = -1 +$script:cfgChildLen = 0 +$script:cfgTextLoaded = $false + +function Initialize-ConfigText { + if ($script:cfgTextLoaded) { return } + $script:cfgTextLoaded = $true + if (-not $script:configDir) { return } + $cfgPath = Join-Path $script:configDir "Configuration.xml" + if (-not (Test-Path $cfgPath)) { return } + try { + $script:cfgText = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8) + } catch { + $script:cfgText = $null + return + } + $s = $script:cfgText.IndexOf('', [System.StringComparison]::Ordinal) + $e = $script:cfgText.LastIndexOf('', [System.StringComparison]::Ordinal) + if ($s -ge 0 -and $e -gt $s) { + $script:cfgChildStart = $s + $script:cfgChildLen = $e - $s + } +} + +function Test-ConfigIsExtension { + Initialize-ConfigText + if (-not $script:cfgText) { return $false } + return $script:cfgText.Contains("ConfigurationExtensionPurpose") +} + +# $true — объект есть в составе; $false — нет; $null — состав неизвестен (нет Configuration.xml +# или в нём нет ChildObjects), тогда вызывающий оставляет мягкий уровень. +function Test-InConfigComposition([string]$kind, [string]$name) { + Initialize-ConfigText + if ($script:cfgChildStart -lt 0) { return $null } + $needle = "<$kind>$name" + if ($script:cfgText.IndexOf($needle, $script:cfgChildStart, $script:cfgChildLen, [System.StringComparison]::Ordinal) -ge 0) { + return $true + } + # Промах по точному совпадению — сверяем без учёта регистра, как это делает платформа. + # Порядок именно такой: Ordinal на порядок дешевле, а промахи редки. + return ($script:cfgText.IndexOf($needle, $script:cfgChildStart, $script:cfgChildLen, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) +} + # --- Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации --- -# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем — -# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения. +# Уровень выбирается по составу конфигурации: типа нет в ChildObjects — «Неизвестное имя типа» при +# загрузке (ERROR); объект в составе есть, а файла в выгрузке нет — частичная выгрузка (WARN). +# Расширения (CFE) пропускаем — их типы ссылаются на объекты базовой конфигурации, которых в выгрузке +# расширения нет. if ($script:configDir) { - $isExtension = $false - $cfgXmlPath = Join-Path $script:configDir "Configuration.xml" - if (Test-Path $cfgXmlPath) { - $cfgContent = [System.IO.File]::ReadAllText($cfgXmlPath, [System.Text.Encoding]::UTF8) - if ($cfgContent.Contains("ConfigurationExtensionPurpose")) { $isExtension = $true } - } + $isExtension = Test-ConfigIsExtension if (-not $isExtension) { $refDirMap = @{ "CatalogRef"="Catalogs"; "DocumentRef"="Documents"; "EnumRef"="Enums" @@ -1486,7 +1538,9 @@ if ($script:configDir) { } $typeNodes = $xmlDoc.SelectNodes("//v8:Type", $ns) $checkedRefs = @{} # refKey -> $true если найден; для OK-условия - $missingRefs = @{} # refKey -> refDir + $missingRefs = @{} # refKey -> refDir; объект есть в составе, файла в выгрузке нет + $absentRefs = @{} # refKey -> refDir; объекта нет в составе конфигурации + $unknownRefs = @{} # refKey -> refDir; состав неизвестен (Configuration.xml без ChildObjects) foreach ($tn in $typeNodes) { $tv = $tn.InnerText.Trim() if (-not $tv) { continue } @@ -1506,14 +1560,35 @@ if ($script:configDir) { $checkedRefs[$refKey] = $true } else { $checkedRefs[$refKey] = $false - $missingRefs[$refKey] = $refDir + # Вид метаданных в ChildObjects — это тип без суффикса Ref (CatalogRef -> Catalog); + # DefinedType суффикса не имеет и пишется в состав как есть. + $refKindTag = if ($refCat.EndsWith("Ref")) { $refCat.Substring(0, $refCat.Length - 3) } else { $refCat } + $inComposition = Test-InConfigComposition $refKindTag $refName + if ($inComposition -eq $false) { + $absentRefs[$refKey] = $refDir + } elseif ($inComposition -eq $true) { + $missingRefs[$refKey] = $refDir + } else { + $unknownRefs[$refKey] = $refDir + } + } + } + if ($absentRefs.Count -gt 0) { + foreach ($ak in ($absentRefs.Keys | Sort-Object)) { + Report-Error "16. Ссылочный тип '$ak' — объекта нет в составе конфигурации ($($absentRefs[$ak])/) — «Неизвестное имя типа» при загрузке" } } if ($missingRefs.Count -gt 0) { foreach ($mk in ($missingRefs.Keys | Sort-Object)) { - Report-Warn "16. Ссылочный тип '$mk' не найден в конфигурации ($($missingRefs[$mk])/) — при загрузке будет ошибка неизвестного типа" + Report-Warn "16. Ссылочный тип '$mk' — объект есть в составе конфигурации, файла объекта в выгрузке нет ($($missingRefs[$mk])/)" } - } elseif ($checkedRefs.Count -gt 0) { + } + if ($unknownRefs.Count -gt 0) { + foreach ($uk in ($unknownRefs.Keys | Sort-Object)) { + Report-Warn "16. Ссылочный тип '$uk' не найден в конфигурации ($($unknownRefs[$uk])/)" + } + } + if ($absentRefs.Count -eq 0 -and $missingRefs.Count -eq 0 -and $unknownRefs.Count -eq 0 -and $checkedRefs.Count -gt 0) { Report-OK "16. Reference types: $($checkedRefs.Count) resolved" } } @@ -1590,6 +1665,11 @@ if ($mdRefNodes -and $mdRefNodes.Count -gt 0) { # регистрацию формы в ChildObjects — работает и на одиночном файле; для чужого и общей формы нужна # конфигурация. Заимствованные объекты расширения (ObjectBelonging=Adopted) пропускаем: их формы # живут в основной конфигурации, в выгрузке расширения их нет. +# +# Уровень везде выбирается по составу, а не по наличию файла (см. Test-InConfigComposition): +# нет в ChildObjects — платформа откажет и при полной, и при частичной загрузке (ERROR); +# в составе есть, а файла в выгрузке нет — это фрагмент частичной выгрузки, и загрузится он или нет, +# зависит от состояния конфигурации БД, которого валидатору не видно (WARN). $formOwnerDirMap = @{ "Catalog"="Catalogs"; "Document"="Documents"; "DocumentJournal"="DocumentJournals" @@ -1606,14 +1686,7 @@ $belongingNode = $typeNode.SelectSingleNode("md:Properties/md:ObjectBelonging", $isAdopted = $belongingNode -and $belongingNode.InnerText.Trim() -eq "Adopted" if (-not $isAdopted) { - $isExtension20 = $false - if ($script:configDir) { - $cfgXmlPath20 = Join-Path $script:configDir "Configuration.xml" - if (Test-Path $cfgXmlPath20) { - $cfgContent20 = [System.IO.File]::ReadAllText($cfgXmlPath20, [System.Text.Encoding]::UTF8) - if ($cfgContent20.Contains("ConfigurationExtensionPurpose")) { $isExtension20 = $true } - } - } + $isExtension20 = Test-ConfigIsExtension # формы своего объекта: имена из ChildObjects (сравнение регистронезависимое — как у платформы) $ownForms = @{} @@ -1656,8 +1729,13 @@ if (-not $isAdopted) { $cfDir = Join-Path (Join-Path $script:configDir "CommonForms") $parts[1] $cfOk = (Test-Path "$cfDir.xml") -or (Test-Path (Join-Path (Join-Path $cfDir "Ext") "Form.xml")) -or (Test-Path (Join-Path $cfDir "Form.xml")) if (-not $cfOk) { - Report-Error "20. $tag '$ref' — общая форма не найдена в конфигурации (CommonForms/$($parts[1])) — «Неизвестный объект метаданных» при загрузке" - $formRefBad = $true + $cfInComposition = Test-InConfigComposition "CommonForm" $parts[1] + if ($cfInComposition -eq $true) { + Report-Warn "20. $tag '$ref' — общая форма есть в составе конфигурации, файла формы в выгрузке нет (CommonForms/$($parts[1]))" + } else { + Report-Error "20. $tag '$ref' — общей формы нет в составе конфигурации (CommonForms/$($parts[1])) — «Неизвестный объект метаданных» при загрузке" + $formRefBad = $true + } } continue } @@ -1675,8 +1753,16 @@ if (-not $isAdopted) { Report-Error "20. $tag '$ref' — форма '$refForm' не зарегистрирована в ChildObjects объекта (есть: $known) — «Неизвестный объект метаданных» при загрузке" $formRefBad = $true } elseif ((Test-Path $ownDir) -and -not (Test-FormFile20 $ownDir $refForm)) { - Report-Error "20. $tag '$ref' — форма зарегистрирована в ChildObjects, но файл формы отсутствует ($objName/Forms/$refForm)" - $formRefBad = $true + # Форма в составе объекта есть, файла нет. Для дерева, претендующего на полноту + # (рядом лежит Configuration.xml), это ошибка целостности — полная загрузка упадёт + # на «Файл объекта не существует». Для фрагмента частичной выгрузки — норма: + # такой файл грузится через -listFile слиянием с конфигурацией БД. + if ($script:configDir) { + Report-Error "20. $tag '$ref' — форма зарегистрирована в ChildObjects, но файл формы отсутствует ($objName/Forms/$refForm)" + $formRefBad = $true + } else { + Report-Warn "20. $tag '$ref' — форма есть в ChildObjects, файла формы в выгрузке нет ($objName/Forms/$refForm)" + } } continue } @@ -1690,7 +1776,15 @@ if (-not $isAdopted) { } $refObjXml = Join-Path (Join-Path $script:configDir $refDir20) "$refObj.xml" if (-not (Test-Path $refObjXml)) { - Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' не найден в конфигурации ($refDir20/)" + $objInComposition = Test-InConfigComposition $refKind $refObj + if ($objInComposition -eq $false) { + Report-Error "20. $tag '$ref' — объекта '$refKind.$refObj' нет в составе конфигурации ($refDir20/) — «Неизвестный объект метаданных» при загрузке" + $formRefBad = $true + } elseif ($objInComposition -eq $true) { + Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' есть в составе конфигурации, файла объекта в выгрузке нет ($refDir20/)" + } else { + Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' не найден в конфигурации ($refDir20/)" + } continue } if (-not (Test-FormFile20 (Join-Path (Join-Path $script:configDir $refDir20) $refObj) $refForm)) { diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index a58fe929b..0f86ee27f 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.py +++ b/.claude/skills/meta-validate/scripts/meta-validate.py @@ -1,4 +1,4 @@ -# meta-validate v1.21 — Validate 1C metadata object structure (Python port) +# meta-validate v1.22 — Validate 1C metadata object structure (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -1388,21 +1388,77 @@ if child_obj_node is not None: if check15_ok and cmd_count > 0: report_ok(f"15. Commands: {cmd_count} command(s), groups valid") +# ── Состав конфигурации (ChildObjects из Configuration.xml) ── +# Платформа судит о существовании объекта по СОСТАВУ, а не по наличию файла. Файла может не быть +# в частичной выгрузке: такой фрагмент грузится через /LoadConfigFromFiles -listFile слиянием с базой, +# и ссылка на невыгруженный объект остаётся рабочей. Отсюда два разных исхода: +# нет в составе -> платформа отвергнет загрузку всегда -> ERROR +# в составе, файла нет -> полная загрузка упадёт, частичная пройдёт -> WARN +# ChildObjects конфигурации — плоский список <Вид>Имя, поэтому ищем подстроку в границах секции +# без копирования и без разбора XML: batch-режим порождает процесс на объект, и полная карта (~100 мс) +# оплачивалась бы каждым объектом. + +_cfg_text = None +_cfg_child_lower = None +_cfg_child_start = -1 +_cfg_child_end = -1 +_cfg_text_loaded = False + + +def _init_config_text(): + global _cfg_text, _cfg_child_start, _cfg_child_end, _cfg_text_loaded + if _cfg_text_loaded: + return + _cfg_text_loaded = True + if not config_dir: + return + cfg_path = os.path.join(config_dir, "Configuration.xml") + if not os.path.exists(cfg_path): + return + try: + with open(cfg_path, "r", encoding="utf-8") as f: + _cfg_text = f.read() + except Exception: + _cfg_text = None + return + s = _cfg_text.find("") + e = _cfg_text.rfind("") + if s >= 0 and e > s: + _cfg_child_start = s + _cfg_child_end = e + + +def config_is_extension(): + _init_config_text() + return bool(_cfg_text) and "ConfigurationExtensionPurpose" in _cfg_text + + +def in_config_composition(kind, name): + """True — объект есть в составе; False — нет; None — состав неизвестен + (нет Configuration.xml или в нём нет ChildObjects), тогда вызывающий оставляет мягкий уровень.""" + global _cfg_child_lower + _init_config_text() + if _cfg_child_start < 0: + return None + needle = "<{0}>{1}".format(kind, name) + if _cfg_text.find(needle, _cfg_child_start, _cfg_child_end) >= 0: + return True + # Промах по точному совпадению — сверяем без учёта регистра, как это делает платформа. + # Порядок именно такой: точный поиск на порядок дешевле, а промахи редки. Нижний регистр + # берём от СРЕЗА и проверяем факт вхождения: смещения в lower() совпадать с оригиналом не обязаны. + if _cfg_child_lower is None: + _cfg_child_lower = _cfg_text[_cfg_child_start:_cfg_child_end].lower() + return needle.lower() in _cfg_child_lower + + # ── Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации ── -# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем — -# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения. +# Уровень выбирается по составу конфигурации: типа нет в ChildObjects — «Неизвестное имя типа» при +# загрузке (ERROR); объект в составе есть, а файла в выгрузке нет — частичная выгрузка (WARN). +# Расширения (CFE) пропускаем — их типы ссылаются на объекты базовой конфигурации, которых в выгрузке +# расширения нет. if config_dir: - is_extension = False - cfg_xml_path = os.path.join(config_dir, "Configuration.xml") - if os.path.exists(cfg_xml_path): - try: - with open(cfg_xml_path, "r", encoding="utf-8") as f: - cfg_content = f.read() - if "ConfigurationExtensionPurpose" in cfg_content: - is_extension = True - except Exception: - pass + is_extension = config_is_extension() if not is_extension: ref_dir_map = { "CatalogRef": "Catalogs", "DocumentRef": "Documents", "EnumRef": "Enums", @@ -1411,7 +1467,9 @@ if config_dir: "ExchangePlanRef": "ExchangePlans", "TaskRef": "Tasks", "DefinedType": "DefinedTypes", } checked_refs = {} # ref_key -> найден ли; для условия OK - missing_refs = {} # ref_key -> ref_dir + missing_refs = {} # ref_key -> ref_dir; объект есть в составе, файла в выгрузке нет + absent_refs = {} # ref_key -> ref_dir; объекта нет в составе конфигурации + unknown_refs = {} # ref_key -> ref_dir; состав неизвестен (Configuration.xml без ChildObjects) for tn in find_all(root, ".//v8:Type"): tv = inner_text(tn).strip() if not tv: @@ -1436,11 +1494,23 @@ if config_dir: checked_refs[ref_key] = True else: checked_refs[ref_key] = False - missing_refs[ref_key] = ref_dir - if missing_refs: - for mk in sorted(missing_refs): - report_warn(f"16. Ссылочный тип '{mk}' не найден в конфигурации ({missing_refs[mk]}/) — при загрузке будет ошибка неизвестного типа") - elif checked_refs: + # Вид метаданных в ChildObjects — это тип без суффикса Ref (CatalogRef -> Catalog); + # DefinedType суффикса не имеет и пишется в состав как есть. + ref_kind_tag = ref_cat[:-3] if ref_cat.endswith("Ref") else ref_cat + in_composition = in_config_composition(ref_kind_tag, ref_name) + if in_composition is False: + absent_refs[ref_key] = ref_dir + elif in_composition is True: + missing_refs[ref_key] = ref_dir + else: + unknown_refs[ref_key] = ref_dir + for ak in sorted(absent_refs): + report_error(f"16. Ссылочный тип '{ak}' — объекта нет в составе конфигурации ({absent_refs[ak]}/) — «Неизвестное имя типа» при загрузке") + for mk in sorted(missing_refs): + report_warn(f"16. Ссылочный тип '{mk}' — объект есть в составе конфигурации, файла объекта в выгрузке нет ({missing_refs[mk]}/)") + for uk in sorted(unknown_refs): + report_warn(f"16. Ссылочный тип '{uk}' не найден в конфигурации ({unknown_refs[uk]}/)") + if not absent_refs and not missing_refs and not unknown_refs and checked_refs: report_ok(f"16. Reference types: {len(checked_refs)} resolved") # ── Check 18: свойства, появившиеся в новых версиях формата ── @@ -1510,6 +1580,11 @@ if md_ref_nodes: # регистрацию формы в ChildObjects — работает и на одиночном файле; для чужого и общей формы нужна # конфигурация. Заимствованные объекты расширения (ObjectBelonging=Adopted) пропускаем: их формы # живут в основной конфигурации, в выгрузке расширения их нет. +# +# Уровень везде выбирается по составу, а не по наличию файла (см. in_config_composition): +# нет в ChildObjects — платформа откажет и при полной, и при частичной загрузке (ERROR); +# в составе есть, а файла в выгрузке нет — это фрагмент частичной выгрузки, и загрузится он или нет, +# зависит от состояния конфигурации БД, которого валидатору не видно (WARN). form_owner_dir_map = { "Catalog": "Catalogs", "Document": "Documents", "DocumentJournal": "DocumentJournals", @@ -1537,16 +1612,7 @@ def _form_file_exists_20(base_dir, form_name): if not is_adopted: - is_extension_20 = False - if config_dir: - cfg_xml_path_20 = os.path.join(config_dir, "Configuration.xml") - if os.path.exists(cfg_xml_path_20): - try: - with open(cfg_xml_path_20, "r", encoding="utf-8") as f: - if "ConfigurationExtensionPurpose" in f.read(): - is_extension_20 = True - except Exception: - pass + is_extension_20 = config_is_extension() # формы своего объекта: имена из ChildObjects (сравнение регистронезависимое — как у платформы) own_forms = {} @@ -1585,9 +1651,13 @@ if not is_adopted: or os.path.exists(os.path.join(cf_dir, "Ext", "Form.xml")) or os.path.exists(os.path.join(cf_dir, "Form.xml"))) if not cf_ok: - report_error(f"20. {tag} '{ref}' — общая форма не найдена в конфигурации " - f"(CommonForms/{parts[1]}) — «Неизвестный объект метаданных» при загрузке") - form_ref_bad = True + if in_config_composition("CommonForm", parts[1]) is True: + report_warn(f"20. {tag} '{ref}' — общая форма есть в составе конфигурации, " + f"файла формы в выгрузке нет (CommonForms/{parts[1]})") + else: + report_error(f"20. {tag} '{ref}' — общей формы нет в составе конфигурации " + f"(CommonForms/{parts[1]}) — «Неизвестный объект метаданных» при загрузке") + form_ref_bad = True continue if len(parts) != 4 or parts[2] != "Form": @@ -1604,9 +1674,17 @@ if not is_adopted: f"ChildObjects объекта (есть: {known}) — «Неизвестный объект метаданных» при загрузке") form_ref_bad = True elif os.path.isdir(own_dir) and not _form_file_exists_20(own_dir, ref_form): - report_error(f"20. {tag} '{ref}' — форма зарегистрирована в ChildObjects, но файл " - f"формы отсутствует ({obj_name}/Forms/{ref_form})") - form_ref_bad = True + # Форма в составе объекта есть, файла нет. Для дерева, претендующего на полноту + # (рядом лежит Configuration.xml), это ошибка целостности — полная загрузка упадёт + # на «Файл объекта не существует». Для фрагмента частичной выгрузки — норма: + # такой файл грузится через -listFile слиянием с конфигурацией БД. + if config_dir: + report_error(f"20. {tag} '{ref}' — форма зарегистрирована в ChildObjects, но файл " + f"формы отсутствует ({obj_name}/Forms/{ref_form})") + form_ref_bad = True + else: + report_warn(f"20. {tag} '{ref}' — форма есть в ChildObjects, файла формы " + f"в выгрузке нет ({obj_name}/Forms/{ref_form})") continue # чужой объект (например журнал документов) — нужна конфигурация @@ -1618,7 +1696,16 @@ if not is_adopted: continue ref_obj_xml = os.path.join(config_dir, ref_dir_20, ref_obj + ".xml") if not os.path.exists(ref_obj_xml): - report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' не найден в конфигурации ({ref_dir_20}/)") + obj_in_composition = in_config_composition(ref_kind, ref_obj) + if obj_in_composition is False: + report_error(f"20. {tag} '{ref}' — объекта '{ref_kind}.{ref_obj}' нет в составе " + f"конфигурации ({ref_dir_20}/) — «Неизвестный объект метаданных» при загрузке") + form_ref_bad = True + elif obj_in_composition is True: + report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' есть в составе " + f"конфигурации, файла объекта в выгрузке нет ({ref_dir_20}/)") + else: + report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' не найден в конфигурации ({ref_dir_20}/)") continue if not _form_file_exists_20(os.path.join(config_dir, ref_dir_20, ref_obj), ref_form): report_error(f"20. {tag} '{ref}' — форма '{ref_form}' не найдена у объекта " diff --git a/tests/skills/cases/meta-validate/error-commonform-absent.json b/tests/skills/cases/meta-validate/error-commonform-absent.json new file mode 100644 index 000000000..b07cf6f92 --- /dev/null +++ b/tests/skills/cases/meta-validate/error-commonform-absent.json @@ -0,0 +1,9 @@ +{ + "name": "Ссылка на общую форму, которой нет в составе конфигурации — ошибка", + "setup": "fixture:catalog-commonform-absent", + "params": { "objectPath": "Catalogs/Товары.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "общей формы нет в составе конфигурации" + } +} diff --git a/tests/skills/cases/meta-validate/error-default-form-file-missing.json b/tests/skills/cases/meta-validate/error-default-form-file-missing.json deleted file mode 100644 index 39284204e..000000000 --- a/tests/skills/cases/meta-validate/error-default-form-file-missing.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Валидатор находит ошибку: форма зарегистрирована в ChildObjects, но файла формы нет", - "setup": "fixture:catalog-form-file-missing", - "params": { "objectPath": "Catalogs/Товары.xml" }, - "expectError": true, - "expect": { - "stdoutContains": "файл формы отсутствует" - } -} diff --git a/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json b/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json new file mode 100644 index 000000000..16b9c86e9 --- /dev/null +++ b/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json @@ -0,0 +1,9 @@ +{ + "name": "Ссылка на форму чужого объекта, которого нет в составе конфигурации — ошибка (#84)", + "setup": "fixture:catalog-foreign-form-absent", + "params": { "objectPath": "Catalogs/Товары.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "объекта 'Document.НетТакого' нет в составе конфигурации" + } +} diff --git a/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json b/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json new file mode 100644 index 000000000..94fb766c9 --- /dev/null +++ b/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json @@ -0,0 +1,9 @@ +{ + "name": "Полная выгрузка: форма в ChildObjects, а файла формы нет — ошибка целостности", + "setup": "fixture:catalog-form-file-missing-full-tree", + "params": { "objectPath": "Catalogs/Товары.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "но файл формы отсутствует" + } +} diff --git a/tests/skills/cases/meta-validate/warn-reftype-missing.json b/tests/skills/cases/meta-validate/error-reftype-absent.json similarity index 72% rename from tests/skills/cases/meta-validate/warn-reftype-missing.json rename to tests/skills/cases/meta-validate/error-reftype-absent.json index a958d088d..d073696e1 100644 --- a/tests/skills/cases/meta-validate/warn-reftype-missing.json +++ b/tests/skills/cases/meta-validate/error-reftype-absent.json @@ -1,5 +1,5 @@ { - "name": "Валидатор предупреждает о несуществующем ссылочном типе реквизита (Check 16)", + "name": "Ссылочный тип реквизита на объект, которого нет в составе конфигурации (Check 16)", "setup": "empty-config", "preRun": [ { @@ -9,8 +9,9 @@ } ], "params": { "objectPath": "Catalogs/ТестСсылкаБитая" }, + "expectError": true, "noSnapshot": "meta-validate только читает и печатает — эталон зафиксировал бы выход preRun (meta-compile), а не проверяемого навыка; проверяется stdout", "expect": { - "stdoutContains": "16. Ссылочный тип 'CatalogRef.НетТакогоСправочника'" + "stdoutContains": "16. Ссылочный тип 'CatalogRef.НетТакогоСправочника' — объекта нет в составе конфигурации" } } diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml new file mode 100644 index 000000000..718966fb7 --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml @@ -0,0 +1,93 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + CommonForm.НетТакой + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml new file mode 100644 index 000000000..8f2f14efb --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml new file mode 100644 index 000000000..f3cd4df56 --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml @@ -0,0 +1,93 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + CommonForm.ОбщаяФорма + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml new file mode 100644 index 000000000..41bf33b83 --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + ОбщаяФорма + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml new file mode 100644 index 000000000..b2a42c0cf --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml @@ -0,0 +1,93 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + Document.НетТакого.Form.Ф + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml new file mode 100644 index 000000000..8f2f14efb --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml new file mode 100644 index 000000000..9cf52aa6c --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml @@ -0,0 +1,93 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + Catalog.Прочие.Form.ФормаСписка + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml new file mode 100644 index 000000000..8f2f14efb --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml new file mode 100644 index 000000000..4c6ef67e5 --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml @@ -0,0 +1,93 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + Catalog.Товары.Form.ФормаЭлемента + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl new file mode 100644 index 000000000..5f282702b --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml new file mode 100644 index 000000000..8f2f14efb --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml new file mode 100644 index 000000000..b291157cd --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml @@ -0,0 +1,133 @@ + + + + + + 663a8901-0032-4f18-bb1a-ce2174cbece4 + bb20df17-ebde-4175-9079-c789e3cbd195 + + + 7005f331-5c27-428e-a561-8b0f78595780 + 39d1fb1b-dfb7-414f-af63-39a637b60657 + + + ead16e67-7005-48d1-83cc-dc0b07edee35 + 0d389498-9b1a-4b69-80e1-43a73bd2138d + + + 9c0c6357-31b4-466e-ab3d-7238b5133945 + 791f1ff6-e378-4777-bfd5-09495fb526e0 + + + cdd35860-4d89-4091-8400-c46e656a66d1 + e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + Catalog.Товары.Form.ФормаЭлемента + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + + + + Партнёр + + + ru + Партнёр + + + + + cfg:CatalogRef.Прочие + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + ForItem + DontIndex + Use + Use + + +
ФормаЭлемента
+
+
+
\ No newline at end of file diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml new file mode 100644 index 000000000..8f2f14efb --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml @@ -0,0 +1,253 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + d0bb0360-4e09-4936-8e34-a3dc3851f67e + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + d9499468-cbbe-410c-b456-6f4a6ef7e4e7 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7378dde3-6113-4bb6-93bf-b57ff8406e1f + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 7398f41d-8349-4e40-8925-88bf7b3590bd + + + 51f2d5d8-ea4d-4064-8892-82951750031e + 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd + + + e68182ea-4237-4383-967f-90c1e3370bc7 + 7688edd2-4e1f-4261-acd8-732c551316eb + + + fb282519-d103-4dd3-bc12-cb271d631dfc + 2202f59a-a576-43d5-9b90-52ad63efe348 + + + + ValRepro + + + ru + ValRepro + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + Прочие + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json b/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json new file mode 100644 index 000000000..a56711fbf --- /dev/null +++ b/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json @@ -0,0 +1,13 @@ +{ + "name": "Общая форма есть в составе конфигурации, но не выгружена — предупреждение, не ошибка", + "setup": "fixture:catalog-commonform-not-dumped", + "params": { + "objectPath": "Catalogs/Товары.xml" + }, + "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout", + "skipPlatformVerify": "фикстура — неполная выгрузка: общая форма есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна", + "expect": { + "stdoutContains": "общая форма есть в составе конфигурации, файла формы в выгрузке нет", + "stdoutNotContains": "[ERROR]" + } +} diff --git a/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json b/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json new file mode 100644 index 000000000..7a3b2dae5 --- /dev/null +++ b/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json @@ -0,0 +1,13 @@ +{ + "name": "Чужой объект есть в составе конфигурации, но не выгружен — предупреждение, не ошибка", + "setup": "fixture:catalog-foreign-not-dumped", + "params": { + "objectPath": "Catalogs/Товары.xml" + }, + "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout", + "skipPlatformVerify": "фикстура — неполная выгрузка: объект есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна", + "expect": { + "stdoutContains": "есть в составе конфигурации, файла объекта в выгрузке нет", + "stdoutNotContains": "[ERROR]" + } +} diff --git a/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json b/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json new file mode 100644 index 000000000..580cd6abd --- /dev/null +++ b/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json @@ -0,0 +1,13 @@ +{ + "name": "Фрагмент частичной выгрузки: форма в ChildObjects, файла формы нет — предупреждение, не ошибка", + "setup": "fixture:catalog-form-file-missing", + "params": { + "objectPath": "Catalogs/Товары.xml" + }, + "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout", + "skipPlatformVerify": "фикстура — фрагмент частичной выгрузки (файла формы нет намеренно); платформа грузит такой фрагмент только через -listFile слиянием с базой, полная загрузка невозможна", + "expect": { + "stdoutContains": "файла формы в выгрузке нет", + "stdoutNotContains": "[ERROR]" + } +} diff --git a/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json b/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json new file mode 100644 index 000000000..91b2c15b5 --- /dev/null +++ b/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json @@ -0,0 +1,13 @@ +{ + "name": "Ссылочный тип на объект, который есть в составе, но не выгружен — предупреждение (Check 16)", + "setup": "fixture:catalog-reftype-not-dumped", + "params": { + "objectPath": "Catalogs/Товары.xml" + }, + "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout", + "skipPlatformVerify": "фикстура — неполная выгрузка: объект типа есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна", + "expect": { + "stdoutContains": "16. Ссылочный тип 'CatalogRef.Прочие' — объект есть в составе конфигурации, файла объекта в выгрузке нет", + "stdoutNotContains": "[ERROR]" + } +}