247 lines
8.7 KiB
Python
247 lines
8.7 KiB
Python
from review_engine import review_snapshot
|
|
from semantic_kernel import index_project
|
|
from sir import ReferenceKind, SirSnapshot, SourceRef, UnresolvedReference
|
|
|
|
|
|
def test_review_snapshot_reports_unresolved_references():
|
|
snapshot = SirSnapshot(
|
|
snapshot_id="snapshot.demo",
|
|
project_id="demo",
|
|
unresolved_references=[
|
|
UnresolvedReference(
|
|
reference_id="ref.1",
|
|
kind=ReferenceKind.CALL,
|
|
source_lineage="lineage.procedure.demo",
|
|
target_name="Missing",
|
|
source_ref=SourceRef(source_path="module.bsl", line_start=2),
|
|
)
|
|
],
|
|
)
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert findings[0].title == "Unresolved call"
|
|
assert findings[0].source_path == "module.bsl"
|
|
|
|
|
|
def test_review_snapshot_reports_1c_objects_without_role_access(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-security")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert findings[0].title == "Missing 1C role access"
|
|
assert "Документ.ЗаказПокупателя" in findings[0].message
|
|
|
|
|
|
def test_review_snapshot_reports_external_integrations(tmp_path):
|
|
module = tmp_path / "integration.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура Отправить()
|
|
Адрес = "https://api.example.local/orders";
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-integrations")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(finding.title == "External integration endpoint" for finding in findings)
|
|
|
|
|
|
def test_review_snapshot_reports_unresolved_1c_command_handler(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<Form name="ФормаДокумента" qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента">
|
|
<Command name="Провести" qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента.Провести" action="ПровестиКоманда" />
|
|
</Form>
|
|
</Document>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-ui-handler")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "Unresolved 1C command handler"
|
|
and "ПровестиКоманда" in finding.message
|
|
for finding in findings
|
|
)
|
|
|
|
|
|
def test_review_snapshot_reports_unresolved_1c_form_event_handler(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<Form
|
|
name="ФормаДокумента"
|
|
qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента"
|
|
onCreate="ПриСозданииНаСервере"
|
|
beforeWrite="ПередЗаписью"
|
|
/>
|
|
</Document>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
module = tmp_path / "form_module.bsl"
|
|
module.write_text("Процедура ПриСозданииНаСервере()\nКонецПроцедуры\n", encoding="utf-8")
|
|
snapshot = index_project(tmp_path, project_id="review-form-handler")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "Unresolved 1C form event handler"
|
|
and "ПередЗаписью" in finding.message
|
|
for finding in findings
|
|
)
|
|
assert not any(
|
|
finding.title == "Unresolved 1C form event handler"
|
|
and "ПриСозданииНаСервере" in finding.message
|
|
for finding in findings
|
|
)
|
|
|
|
|
|
def test_review_snapshot_reports_empty_1c_tabular_section(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<TabularSection name="Услуги" qualifiedName="Документ.ЗаказПокупателя.Услуги" />
|
|
</Document>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-empty-tabular-section")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "Empty 1C tabular section"
|
|
and "Документ.ЗаказПокупателя.Услуги" in finding.message
|
|
for finding in findings
|
|
)
|
|
|
|
|
|
def test_review_snapshot_reports_tabular_section_without_subject_column(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<TabularSection name="Товары" qualifiedName="Документ.ЗаказПокупателя.Товары">
|
|
<Attribute name="Количество" qualifiedName="Документ.ЗаказПокупателя.Товары.Количество" />
|
|
</TabularSection>
|
|
</Document>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-no-subject-column")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "No subject column in 1C tabular section"
|
|
and finding.severity.value == "INFO"
|
|
and "Документ.ЗаказПокупателя.Товары" in finding.message
|
|
for finding in findings
|
|
)
|
|
|
|
|
|
def test_review_snapshot_accepts_tabular_section_with_subject_column(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<TabularSection name="Товары" qualifiedName="Документ.ЗаказПокупателя.Товары">
|
|
<Attribute name="Номенклатура" qualifiedName="Документ.ЗаказПокупателя.Товары.Номенклатура" />
|
|
<Attribute name="Количество" qualifiedName="Документ.ЗаказПокупателя.Товары.Количество" />
|
|
</TabularSection>
|
|
</Document>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-subject-column")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert not any(finding.title == "No subject column in 1C tabular section" for finding in findings)
|
|
|
|
|
|
def test_review_snapshot_reports_document_posting_without_register_writes(tmp_path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
module = tmp_path / "Documents" / "ЗаказПокупателя" / "Ext" / "ObjectModule.bsl"
|
|
module.parent.mkdir(parents=True)
|
|
module.write_text("Процедура Проведение()\nКонецПроцедуры\n", encoding="utf-8")
|
|
snapshot = index_project(tmp_path, project_id="review-document-posting")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "Document posting has no register writes"
|
|
and finding.severity.value == "INFO"
|
|
and "Документ.ЗаказПокупателя" in finding.message
|
|
for finding in findings
|
|
)
|
|
|
|
|
|
def test_review_snapshot_reports_register_read_write_dependency(tmp_path):
|
|
module = tmp_path / "module.bsl"
|
|
module.write_text(
|
|
"""
|
|
Процедура ПроверитьОстатки()
|
|
Запрос = Новый Запрос;
|
|
Запрос.Текст =
|
|
"ВЫБРАТЬ
|
|
Остатки.Номенклатура
|
|
ИЗ
|
|
РегистрНакопления.ОстаткиТоваров КАК Остатки";
|
|
КонецПроцедуры
|
|
|
|
Процедура Проведение()
|
|
Движения.ОстаткиТоваров.Записать();
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
snapshot = index_project(tmp_path, project_id="review-query-conflict")
|
|
|
|
findings = review_snapshot(snapshot)
|
|
|
|
assert any(
|
|
finding.title == "Register read/write dependency"
|
|
and "ПроверитьОстатки" in finding.message
|
|
and "Проведение" in finding.message
|
|
for finding in findings
|
|
)
|