153 lines
5.3 KiB
Python
153 lines
5.3 KiB
Python
from pathlib import Path
|
|
|
|
from semantic_kernel import index_project
|
|
from sir import EdgeKind, NodeKind, validate_snapshot
|
|
|
|
|
|
def test_index_project_builds_valid_snapshot(tmp_path: Path):
|
|
module = tmp_path / "demo_module.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура Проведение()
|
|
ПроверитьОстатки();
|
|
Движения.ОстаткиТоваров.Записать();
|
|
КонецПроцедуры
|
|
|
|
Процедура ПроверитьОстатки()
|
|
Запрос = Новый Запрос;
|
|
Запрос.Текст =
|
|
"ВЫБРАТЬ
|
|
Остатки.Номенклатура
|
|
ИЗ
|
|
РегистрНакопления.ОстаткиТоваров КАК Остатки";
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
snapshot = index_project(tmp_path, project_id="demo")
|
|
|
|
validate_snapshot(snapshot)
|
|
assert any(node.kind == NodeKind.MODULE for node in snapshot.nodes)
|
|
assert any(node.kind == NodeKind.PROCEDURE and node.name == "Проведение" for node in snapshot.nodes)
|
|
assert any(node.kind == NodeKind.QUERY for node in snapshot.nodes)
|
|
assert any(node.kind == NodeKind.REGISTER and node.name == "ОстаткиТоваров" for node in snapshot.nodes)
|
|
assert any(edge.kind == EdgeKind.CALLS for edge in snapshot.edges)
|
|
assert any(edge.kind == EdgeKind.READS_TABLE for edge in snapshot.edges)
|
|
assert any(edge.kind == EdgeKind.WRITES for edge in snapshot.edges)
|
|
|
|
|
|
def test_index_project_builds_integration_endpoint_nodes(tmp_path: Path):
|
|
module = tmp_path / "integration.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура Отправить()
|
|
Адрес = "https://api.example.local/orders";
|
|
Объект = Новый COMОбъект("V83.Application");
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
snapshot = index_project(tmp_path, project_id="integrations")
|
|
|
|
assert any(node.kind == NodeKind.INTEGRATION_ENDPOINT for node in snapshot.nodes)
|
|
assert any(edge.kind == EdgeKind.USES_INTEGRATION for edge in snapshot.edges)
|
|
|
|
|
|
def test_index_project_extracts_inline_new_query(tmp_path: Path):
|
|
module = tmp_path / "query_module.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура ПроверитьКонтрагента()
|
|
Запрос = Новый Запрос("ВЫБРАТЬ Контрагенты.Ссылка ИЗ Справочник.Контрагенты КАК Контрагенты");
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
snapshot = index_project(tmp_path, project_id="inline-query")
|
|
|
|
query = next(node for node in snapshot.nodes if node.kind == NodeKind.QUERY)
|
|
assert "Справочник.Контрагенты" in query.attributes["query_text"]
|
|
assert any(
|
|
edge.kind == EdgeKind.READS_TABLE
|
|
and any(node.lineage_id == edge.target_lineage and node.qualified_name == "Справочник.Контрагенты" for node in snapshot.nodes)
|
|
for edge in snapshot.edges
|
|
)
|
|
|
|
|
|
def test_index_project_prefers_same_module_routine_for_duplicate_names(tmp_path: Path):
|
|
shared = tmp_path / "a_shared.bsl"
|
|
shared.write_text(
|
|
"""
|
|
Процедура ПроверитьОстатки()
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
document_module = tmp_path / "z_document.bsl"
|
|
document_module.write_text(
|
|
"""
|
|
Процедура Проведение()
|
|
ПроверитьОстатки();
|
|
КонецПроцедуры
|
|
|
|
Процедура ПроверитьОстатки()
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
snapshot = index_project(tmp_path, project_id="duplicate-routines")
|
|
|
|
local_target = next(
|
|
node for node in snapshot.nodes if node.qualified_name == "z_document.ПроверитьОстатки"
|
|
)
|
|
assert any(
|
|
edge.kind == EdgeKind.CALLS and edge.target_lineage == local_target.lineage_id
|
|
for edge in snapshot.edges
|
|
)
|
|
|
|
|
|
def test_index_project_records_malformed_bsl_diagnostics(tmp_path: Path):
|
|
module = tmp_path / "broken.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура Проведение()
|
|
Запрос = Новый Запрос;
|
|
Запрос.Текст =
|
|
"ВЫБРАТЬ
|
|
Товары.Ссылка
|
|
ИЗ
|
|
Справочник.Номенклатура КАК Товары"
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
snapshot = index_project(tmp_path, project_id="broken")
|
|
|
|
assert {diagnostic.code for diagnostic in snapshot.diagnostics} == {
|
|
"BSL_UNCLOSED_QUERY",
|
|
"BSL_UNCLOSED_ROUTINE",
|
|
}
|
|
|
|
|
|
def test_index_project_skips_invalid_xml_and_records_diagnostic(tmp_path: Path):
|
|
valid_xml = tmp_path / "valid.xml"
|
|
valid_xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Catalog name="Контрагенты" qualifiedName="Справочник.Контрагенты" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
broken_xml = tmp_path / "broken.mdo"
|
|
broken_xml.write_text("<mdclass:Catalog xmlns:mdclass=", encoding="utf-8")
|
|
|
|
snapshot = index_project(tmp_path, project_id="broken-xml")
|
|
|
|
assert any(node.qualified_name == "Справочник.Контрагенты" for node in snapshot.nodes)
|
|
assert any(diagnostic.code == "XML_PARSE_ERROR" for diagnostic in snapshot.diagnostics)
|