fix(xdto): три дефекта, найденных платформенной верификацией снэпшотов

verify-snapshots загружает результат каждого кейса в 1С. Раньше навыки xdto
через него не проходили вовсе; первый прогон дал 5 из 9. Ни корпусная сверка,
ни валидатор такого не ловили: корпус состоит из заведомо валидных пакетов,
а синтетические кейсы до сих пор в базу не грузились.

1. fixed. В модели XDTO это булев флаг, значение лежит в default; в XSD наоборот —
   fixed="V" несёт значение. Компилятор писал значение прямо в fixed, и платформа
   отвергала пакет («Отсутствует фиксированное значение свойства»). Перевод сделан
   в обе стороны; по принципу прощающего ввода принимается и модельная форма через
   зеркало xdto:fixed. Отображение выведено по корпусу: fixed встречается только
   вместе с default, значений всего два.

2. Импорт на несуществующий пакет платформа отвергает («xdto-package-3.3 …
   не определен»), а у нас проверки не было. Добавлена ошибка валидатора и,
   что важнее, предупреждение прямо на сборке — отказ при db-update дешевле
   поймать на шаг раньше. Правило пришлось калибровать корпусом: сначала оно
   дало 67 ложных срабатываний на платформенных пространствах имён, их список
   выведен и исключён.

3. localName проверяется как NCName — фикстура с пробелом в имени была негодной,
   заменена на реалистичный дефис (name="alpha_3" localName="alpha-3").

Харнесс получил skipPlatformVerify с обязательной причиной: результат
set-namespace невалиден by design, операция намеренно оставляет висящий импорт
у зависящего пакета.

Итог: 9/9 компилятора, 9/10 + 1 осознанный пропуск у edit, round-trip 760/760,
валидатор 0 ложных, 40 тестов на обоих рантаймах.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-26 14:51:08 +03:00
co-authored by Claude Opus 5
parent 3eb805f7b0
commit 5d5a1bc36a
33 changed files with 344 additions and 29 deletions
@@ -15,7 +15,7 @@
<xs:complexType name="Контакт" xdto:sequenced="true">
<xs:sequence>
<xs:element name="Комментарий" type="xs:string" minOccurs="0" xdto:form="Element"/>
<xs:element name="Имя с пробелом" type="xs:string" xdto:name="Имя_с_пробелом" minOccurs="0"/>
<xs:element name="alpha-3" type="xs:string" xdto:name="alpha_3" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Представление" type="xs:string" xdto:nillable="true" xdto:lowerBound="0"/>
</xs:complexType>
@@ -0,0 +1,5 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test:other">
<xs:complexType name="ВнешнийТип">
<xs:sequence><xs:element name="Код" type="xs:string"/></xs:sequence>
</xs:complexType>
</xs:schema>
+21 -4
View File
@@ -1,9 +1,26 @@
{
"name": "ссылки на типы: свой ns (dNpN), голое имя, чужой ns с импортом, ref",
"caseFiles": ["refs.xsd"],
"params": { "xsdFile": "refs.xsd" },
"caseFiles": [
"other.xsd",
"refs.xsd"
],
"params": {
"xsdFile": "refs.xsd"
},
"validatePath": "XDTOPackages/refs",
"expect": {
"files": ["XDTOPackages/refs.xml", "XDTOPackages/refs/Ext/Package.bin"]
}
"files": [
"XDTOPackages/refs.xml",
"XDTOPackages/refs/Ext/Package.bin"
]
},
"preRun": [
{
"script": "xdto-compile/scripts/xdto-compile",
"args": {
"-XsdPath": "{workDir}/other.xsd",
"-OutputDir": "{workDir}"
}
}
]
}
@@ -2,7 +2,7 @@
<objectType name="Контакт" sequenced="true">
<property name="Представление" type="xs:string" lowerBound="0" nillable="true" form="Attribute"/>
<property name="Комментарий" type="xs:string" lowerBound="0" form="Element"/>
<property name="Имя_с_пробелом" type="xs:string" lowerBound="0" localName="Имя с пробелом"/>
<property name="alpha_3" type="xs:string" lowerBound="0" localName="alpha-3"/>
</objectType>
<objectType name="ЯвныйПорядок">
<property name="Элемент" type="xs:string"/>
@@ -15,7 +15,7 @@
<xs:complexType name="Контакт" xdto:sequenced="true">
<xs:sequence>
<xs:element name="Комментарий" type="xs:string" minOccurs="0" xdto:form="Element"/>
<xs:element name="Имя с пробелом" type="xs:string" xdto:name="Имя_с_пробелом" minOccurs="0"/>
<xs:element name="alpha-3" type="xs:string" xdto:name="alpha_3" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Представление" type="xs:string" xdto:nillable="true" xdto:lowerBound="0"/>
</xs:complexType>
@@ -8,7 +8,7 @@
<property name="ДоТрёх" type="xs:string" upperBound="3"/>
<property name="Обнуляемый" type="xs:string" lowerBound="0" nillable="true"/>
<property name="СУмолчанием" type="xs:string" default="нет"/>
<property name="Фиксированный" type="xs:string" fixed="1"/>
<property name="Фиксированный" type="xs:string" fixed="true" default="1"/>
<property name="БезТипа"/>
</objectType>
</package>
@@ -246,6 +246,7 @@
</Properties>
<ChildObjects>
<Language>Русский</Language>
<XDTOPackage>other</XDTOPackage>
<XDTOPackage>refs</XDTOPackage>
</ChildObjects>
</Configuration>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<XDTOPackage uuid="UUID-001">
<Properties>
<Name>other</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>other</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Namespace>urn:test:other</Namespace>
</Properties>
</XDTOPackage>
</MetaDataObject>
@@ -0,0 +1,5 @@
<package xmlns="http://v8.1c.ru/8.1/xdto" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="urn:test:other">
<objectType name="ВнешнийТип">
<property name="Код" type="xs:string"/>
</objectType>
</package>
@@ -0,0 +1,5 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test:other">
<xs:complexType name="ВнешнийТип">
<xs:sequence><xs:element name="Код" type="xs:string"/></xs:sequence>
</xs:complexType>
</xs:schema>
@@ -246,6 +246,7 @@
</Properties>
<ChildObjects>
<Language>Русский</Language>
<XDTOPackage>other</XDTOPackage>
<XDTOPackage>top_level_order</XDTOPackage>
</ChildObjects>
</Configuration>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<XDTOPackage uuid="UUID-001">
<Properties>
<Name>other</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>other</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Namespace>urn:test:other</Namespace>
</Properties>
</XDTOPackage>
</MetaDataObject>
@@ -0,0 +1,5 @@
<package xmlns="http://v8.1c.ru/8.1/xdto" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="urn:test:other">
<objectType name="ВнешнийТип">
<property name="Код" type="xs:string"/>
</objectType>
</package>
@@ -0,0 +1,5 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test:other">
<xs:complexType name="ВнешнийТип">
<xs:sequence><xs:element name="Код" type="xs:string"/></xs:sequence>
</xs:complexType>
</xs:schema>
@@ -1,9 +1,25 @@
{
"name": "порядок верхнего уровня: import→property→valueType→objectType независимо от порядка в XSD",
"caseFiles": ["top-level-order.xsd"],
"params": { "xsdFile": "top-level-order.xsd" },
"caseFiles": [
"other.xsd",
"top-level-order.xsd"
],
"params": {
"xsdFile": "top-level-order.xsd"
},
"validatePath": "XDTOPackages/top_level_order",
"expect": {
"files": ["XDTOPackages/top_level_order/Ext/Package.bin"]
}
"files": [
"XDTOPackages/top_level_order/Ext/Package.bin"
]
},
"preRun": [
{
"script": "xdto-compile/scripts/xdto-compile",
"args": {
"-XsdPath": "{workDir}/other.xsd",
"-OutputDir": "{workDir}"
}
}
]
}
@@ -15,7 +15,7 @@
<xs:complexType name="Контакт" xdto:sequenced="true">
<xs:sequence>
<xs:element name="Комментарий" type="xs:string" minOccurs="0" xdto:form="Element"/>
<xs:element name="Имя с пробелом" type="xs:string" xdto:name="Имя_с_пробелом" minOccurs="0"/>
<xs:element name="alpha-3" type="xs:string" xdto:name="alpha_3" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Представление" type="xs:string" xdto:nillable="true" xdto:lowerBound="0"/>
</xs:complexType>
@@ -2,7 +2,7 @@
<objectType name="Контакт" sequenced="true">
<property name="Представление" type="xs:string" lowerBound="0" nillable="true" form="Attribute"/>
<property name="Комментарий" type="xs:string" lowerBound="0" form="Element"/>
<property name="Имя_с_пробелом" type="xs:string" lowerBound="0" localName="Имя с пробелом"/>
<property name="alpha_3" type="xs:string" lowerBound="0" localName="alpha-3"/>
</objectType>
<objectType name="ЯвныйПорядок">
<property name="Элемент" type="xs:string"/>
@@ -15,7 +15,7 @@
<xs:complexType name="Контакт" xdto:sequenced="true">
<xs:sequence>
<xs:element name="Комментарий" type="xs:string" minOccurs="0" xdto:form="Element"/>
<xs:element name="Имя с пробелом" type="xs:string" xdto:name="Имя_с_пробелом" minOccurs="0"/>
<xs:element name="alpha-3" type="xs:string" xdto:name="alpha_3" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Представление" type="xs:string" xdto:nillable="true" xdto:lowerBound="0"/>
</xs:complexType>
@@ -12,7 +12,7 @@
<xs:complexType name="Контакт" xdto:sequenced="true">
<xs:sequence>
<xs:element name="Комментарий" type="xs:string" minOccurs="0" xdto:form="Element"/>
<xs:element name="Имя с пробелом" type="xs:string" minOccurs="0" xdto:name="Имя_с_пробелом"/>
<xs:element name="alpha-3" type="xs:string" minOccurs="0" xdto:name="alpha_3"/>
</xs:sequence>
<xs:attribute name="Представление" type="xs:string" xdto:nillable="true" xdto:lowerBound="0"/>
</xs:complexType>
+9 -1
View File
@@ -1,9 +1,17 @@
{
"name": "добавление импорта",
"caseFiles": [
"common.xsd",
"types.xsd"
],
"preRun": [
{
"script": "xdto-compile/scripts/xdto-compile",
"args": {
"-XsdPath": "{workDir}/common.xsd",
"-OutputDir": "{workDir}"
}
},
{
"script": "xdto-compile/scripts/xdto-compile",
"args": {
@@ -19,7 +27,7 @@
"-Operation",
"add-import",
"-Value",
"urn:test:other",
"urn:test:common",
"-NoValidate"
],
"expect": {
@@ -35,5 +35,6 @@
"XDTOPackages/common/Ext/Package.bin",
"XDTOPackages/common.xml"
]
}
},
"skipPlatformVerify": "смена namespace намеренно оставляет импорт зависящего пакета висящим — это документированное поведение операции"
}
@@ -246,6 +246,7 @@
</Properties>
<ChildObjects>
<Language>Русский</Language>
<XDTOPackage>common</XDTOPackage>
<XDTOPackage>types</XDTOPackage>
</ChildObjects>
</Configuration>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<XDTOPackage uuid="UUID-001">
<Properties>
<Name>common</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>common</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Namespace>urn:test:common</Namespace>
</Properties>
</XDTOPackage>
</MetaDataObject>
@@ -0,0 +1,6 @@
<package xmlns="http://v8.1c.ru/8.1/xdto" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="urn:test:common">
<objectType name="Справочник">
<property name="Код" type="xs:string"/>
<property name="Наименование" type="xs:string"/>
</objectType>
</package>
@@ -1,5 +1,5 @@
<package xmlns="http://v8.1c.ru/8.1/xdto" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="urn:test:types">
<import namespace="urn:test:other"/>
<import namespace="urn:test:common"/>
<valueType name="СуммаТип" base="xs:decimal" totalDigits="18" fractionDigits="2"/>
<valueType name="СчётТип" base="xs:string" length="20">
<pattern>[0-9]{20}</pattern>
@@ -0,0 +1,8 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:test:common" targetNamespace="urn:test:common">
<xs:complexType name="Справочник">
<xs:sequence>
<xs:element name="Код" type="xs:string"/>
<xs:element name="Наименование" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
+16 -2
View File
@@ -686,6 +686,15 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
const workDir = mkdtempSync(join(tmpdir(), `verify-${skillName}-${caseName}-`));
result.workDir = workDir;
// Кейс может осознанно исключаться из платформенной проверки — когда его
// результат невалиден by design (например, операция намеренно оставляет
// висящий импорт). Причина обязательна, молча пропускать нельзя.
if (caseData.skipPlatformVerify) {
result.skipped = true;
result.skipReason = String(caseData.skipPlatformVerify);
return result;
}
// caseFiles — файловый вход кейса (напр. XSD для xdto-compile), как в runner.mjs
for (const rel of caseData.caseFiles || []) {
const src = join(CASES, skillName, rel);
@@ -1434,9 +1443,14 @@ async function main() {
}
const passed = results.filter(r => r.passed).length;
const failed = results.filter(r => !r.passed).length;
const skipped = results.filter(r => r.skipped).length;
const failed = results.filter(r => !r.passed && !r.skipped).length;
console.log(`\n${'='.repeat(60)}`);
console.log(`Results: ${passed} passed, ${failed} failed out of ${results.length}`);
console.log(`Results: ${passed} passed, ${failed} failed`
+ (skipped ? `, ${skipped} skipped` : '') + ` out of ${results.length}`);
for (const r of results.filter(x => x.skipped)) {
console.log(` \u25cb ${r.skill}/${r.case} \u2014 ${r.skipReason}`);
}
writeReport(results);
process.exit(failed > 0 ? 1 : 0);