Files
llm/tests/1c/test_metadata_kind_fixtures.py
T

168 lines
6.2 KiB
Python

from __future__ import annotations
import json
import sys
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
import scripts.check_1c_metadata_kind_fixtures as fixtures # noqa: E402
MANIFEST = ROOT / "config" / "1c_metadata_kind_fixtures.json"
def test_fixture_manifest_is_valid_and_forbids_direct_sql() -> None:
manifest = fixtures.load_json(MANIFEST)
assert fixtures.validate_manifest(manifest) == []
assert manifest["policy"]["direct_sql_write_allowed"] is False
assert manifest["designer"] == {
"required_version": "8.5.1.1236",
"access_mode": "operating_system_integrated_only",
"credential_arguments_allowed": False,
"export_script": "scripts/export_1c_extension_sources.ps1",
}
assert manifest["external_reference"]["usage"] == "external_reference_only_not_vendored"
assert len(manifest["external_reference"]["commit"]) == 40
assert {item["kind"] for item in manifest["fixtures"]} == {
"CalculationRegister",
"Sequence",
"Interface",
}
def test_offline_check_does_not_claim_live_readiness() -> None:
result = fixtures.check_manifest(MANIFEST)
assert result["passed"] is True
assert result["status"] == "manifest_valid"
assert result["counts"] == {"findings": 0, "fixtures": 3, "ready": 0, "gaps": 0}
assert {item["status"] for item in result["fixtures"]} == {"not_checked"}
def test_live_check_distinguishes_ready_missing_and_unconfigured() -> None:
calls: list[tuple[str, dict[str, Any]]] = []
def fake_rpc(_url: str, method: str, payload: dict[str, Any], _timeout: float, _token: str) -> dict[str, Any]:
calls.append((method, payload))
if method == "extension.objects.find":
return {
"status": "ok",
"objects": [
{
"kind": "CalculationRegister",
"name": "tt_РегистрРасчета1",
"guid": "a4dfe8f1-2ce8-43c9-8b41-3deb7238c5d5",
"activation_state": "saved_only",
"extension_guid": "fb26cf42-7609-11f1-828f-005056b0d483",
},
{
"kind": "Catalog",
"name": "tt_Последовательность1",
"guid": "11111111-1111-1111-1111-111111111111",
"activation_state": "saved_only",
},
],
}
return {"status": "ok"}
result = fixtures.check_manifest(MANIFEST, live=True, rpc_call=fake_rpc)
by_kind = {item["kind"]: item for item in result["fixtures"]}
assert by_kind["CalculationRegister"]["status"] == "fixture_ready"
assert by_kind["Sequence"]["status"] == "fixture_missing"
assert by_kind["Interface"]["status"] == "target_not_configured"
assert [item["method"] for item in by_kind["CalculationRegister"]["smoke"]] == [
"metadata.object.get",
"metadata.object.properties",
"metadata.object.attributes",
"metadata.object.related",
]
extension_find_calls = [payload for method, payload in calls if method == "extension.objects.find"]
assert len(extension_find_calls) == 1
calc_find_payload = extension_find_calls[0]
assert "kind" not in calc_find_payload
assert calc_find_payload["use_cache"] is True
assert calc_find_payload["full_scan"] is False
assert calc_find_payload["refresh_cache"] is False
assert result["passed"] is True
assert result["status"] == "gaps_found"
def test_require_ready_fails_when_a_fixture_is_missing() -> None:
def fake_rpc(_url: str, method: str, _payload: dict[str, Any], _timeout: float, _token: str) -> dict[str, Any]:
if method == "metadata.objects.list":
return {"status": "not_found", "objects": []}
return {"status": "not_found", "objects": []}
result = fixtures.check_manifest(
MANIFEST,
live=True,
require_ready=True,
base_overrides={"interface_legacy_base": "legacy_test"},
rpc_call=fake_rpc,
)
assert result["passed"] is False
assert result["counts"]["ready"] == 0
assert result["counts"]["gaps"] == 3
def test_live_check_reuses_extension_scan_transport_failure() -> None:
calls = 0
def fake_rpc(_url: str, _method: str, _payload: dict[str, Any], _timeout: float, _token: str) -> dict[str, Any]:
nonlocal calls
calls += 1
raise TimeoutError("scan timed out")
result = fixtures.check_manifest(MANIFEST, live=True, rpc_call=fake_rpc)
by_kind = {item["kind"]: item for item in result["fixtures"]}
assert calls == 1
assert by_kind["CalculationRegister"]["error"] == "TimeoutError"
assert "probe_error_reused" not in by_kind["CalculationRegister"]
assert by_kind["Sequence"]["error"] == "TimeoutError"
assert by_kind["Sequence"]["probe_error_reused"] is True
def test_manifest_rejects_credential_like_keys(tmp_path: Path) -> None:
value = fixtures.load_json(MANIFEST)
value["fixtures"][0]["password"] = "must-not-be-here"
path = tmp_path / "manifest.json"
path.write_text(json.dumps(value, ensure_ascii=False), encoding="utf-8")
result = fixtures.check_manifest(path)
assert result["passed"] is False
assert any(item["code"] == "credential_key_in_manifest" for item in result["findings"])
def test_manifest_requires_safe_designer_access_and_pinned_reference() -> None:
value = fixtures.load_json(MANIFEST)
value["designer"]["access_mode"] = "interactive_credentials"
value["external_reference"]["commit"] = "main"
findings = fixtures.validate_manifest(value)
assert {item["code"] for item in findings} >= {
"unsafe_designer_access_mode",
"invalid_external_reference_commit",
}
def test_designer_export_script_has_no_user_or_credential_parameters() -> None:
script = (ROOT / "scripts" / "export_1c_extension_sources.ps1").read_text(encoding="utf-8")
assert "/WA+" in script
assert "/N" not in script
assert "/P" not in script
assert "UserName" not in script
assert "Credential" not in script
assert "/DumpConfigToFiles" in script
assert "-Extension" in script