Initial project import

This commit is contained in:
2026-08-14 09:40:51 +03:00
parent 00040e5ce4
commit d7099bf80d
146 changed files with 30509 additions and 1055 deletions
+164
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import json
import sqlite3
import sys
from pathlib import Path
@@ -50,6 +51,80 @@ def configured_layers(monkeypatch, tmp_path: Path) -> None:
monkeypatch.setenv("ONEC_REPOSITORY_STATE_FILE", str(tmp_path / "locks.json"))
def test_repositoryless_base_inherits_test_write_profile_to_discovered_extension(monkeypatch, tmp_path: Path) -> None:
config = {
"upo_test": {
"server": "sql", "database": "upo_test", "user": "reader",
"development_layers": {
"base": {
"repository": {"mode": "none", "connection_state": "not_configured"},
"support": {"mode": "unknown"},
},
},
},
}
extension_guid = "11111111-2222-3333-4444-555555555555"
monkeypatch.setenv("ONEC_SQL_BASES_JSON", json.dumps(config))
monkeypatch.setenv("ONEC_REPOSITORY_STATE_FILE", str(tmp_path / "locks.json"))
payload = {"base_id": "upo_test", "extension_guid": extension_guid}
repository, repository_error = repository_control.repository_config("upo_test", f"extension:{extension_guid}")
assert repository_error is None
assert repository["mode"] == "none"
assert repository["inherited_from_layer"] == "base"
assert repository_control.write_gate(payload)["allowed"] is True
support = repository_control.support_gate(payload)
assert support["allowed"] is True
assert support["status"] == "not_on_support_inherited_no_repository"
def test_repository_policy_is_not_inherited_from_real_base_to_extension(monkeypatch, tmp_path: Path) -> None:
configured_layers(monkeypatch, tmp_path)
repository, error = repository_control.repository_config(
"base", "extension:99999999-2222-3333-4444-555555555555"
)
assert repository is None
assert error["status"] == "layer_not_configured"
def test_repository_state_migrates_once_to_local_sqlite(monkeypatch, tmp_path: Path) -> None:
legacy_path = tmp_path / "locks.json"
state_path = tmp_path / "adapter-state.sqlite"
legacy = {
"requests": {
"rreq-legacy": {
"base_id": "base",
"layer_id": "base",
"status": "cancelled",
"created_at": 1.0,
}
},
"sessions": {},
"audit": [{"event": "legacy_event", "time": 1.0, "base_id": "base"}],
}
legacy_path.write_text(json.dumps(legacy), encoding="utf-8")
original = legacy_path.read_bytes()
monkeypatch.setenv("ONEC_REPOSITORY_STATE_FILE", str(legacy_path))
monkeypatch.setenv("ONEC_ADAPTER_STATE_DB", str(state_path))
state = repository_control._read_state()
assert state["requests"]["rreq-legacy"]["status"] == "cancelled"
assert legacy_path.read_bytes() == original
with sqlite3.connect(state_path) as conn:
assert conn.execute(
"SELECT value FROM adapter_state_meta WHERE key='legacy_repository_state_imported'"
).fetchone()[0] == "1"
assert int(conn.execute(
"SELECT value FROM adapter_state_meta WHERE key='adapter_state_schema_version'"
).fetchone()[0]) >= 2
assert conn.execute("SELECT COUNT(*) FROM repository_lock_requests").fetchone()[0] == 1
assert conn.execute("SELECT COUNT(*) FROM repository_lock_events").fetchone()[0] == 1
def test_repository_backend_and_endpoint_come_only_from_base_settings(monkeypatch, tmp_path: Path) -> None:
configured_base(monkeypatch, tmp_path)
config, error = repository_control.repository_config("base")
@@ -70,6 +145,89 @@ def test_http_runner_profile_does_not_require_local_designer_or_credentials(monk
assert "designer_path" not in configured
def test_activation_debug_probe_calls_dedicated_http_endpoint_without_execution(
monkeypatch,
) -> None:
captured = {}
class Response:
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def read(self):
return json.dumps(
{
"status": "ready",
"runner": {
"kind": "local",
"reachable": True,
"designer_available": True,
"infobase_selector_configured": True,
},
"operation": {
"kind": "/UpdateDBCfg",
"execution_supported": False,
},
"execution": {
"mode": "debug",
"performed": False,
"designer_started": False,
},
"debug_acceptance": {
"accepted": True,
"request_id": "actreq-" + "1" * 32,
"fingerprint": "a" * 64,
"receipt": "b" * 64,
},
}
).encode("utf-8")
def fake_urlopen(request, timeout):
captured["url"] = request.full_url
captured["body"] = json.loads(request.data.decode("utf-8"))
captured["authorization"] = request.headers.get("Authorization")
captured["timeout"] = timeout
return Response()
monkeypatch.setenv("ACTIVATION_RUNNER_TOKEN", "runner-secret")
monkeypatch.setattr(repository_control.urllib.request, "urlopen", fake_urlopen)
result = repository_control.activation_debug_probe(
"upo_test",
{
"runner": {
"kind": "http",
"url": "http://runner:8121",
"token_env": "ACTIVATION_RUNNER_TOKEN",
}
},
layer="base_saved_state",
timeout_seconds=7,
request_id="actreq-" + "1" * 32,
fingerprint="a" * 64,
)
assert result["status"] == "ready"
assert captured == {
"url": "http://runner:8121/configuration/activation/debug",
"body": {
"base_id": "upo_test",
"layer": "base_saved_state",
"mode": "debug",
"request_id": "actreq-" + "1" * 32,
"fingerprint": "a" * 64,
},
"authorization": "Bearer runner-secret",
"timeout": 7,
}
assert result["execution"]["performed"] is False
assert result["execution"]["designer_started"] is False
assert result["debug_acceptance"]["receipt"] == "b" * 64
def test_lock_plan_maps_child_metadata_to_development_owner() -> None:
result = repository_control.lock_plan({"object": "РегистрСведений.Настройки.Реквизит.Код"})
assert result["status"] == "ready"
@@ -121,6 +279,9 @@ def test_manual_lock_request_stays_pending_until_user_confirms_exact_saved_scope
}
pending = repository_control.lock_request_status({"request_id": requested["request_id"]})
assert pending["status"] == "pending_user_lock"
assert pending["base_id"] == "base"
assert pending["objects"] == ["РегистрСведений.Настройки"]
assert pending["native_lock_state"] == "unknown"
assert pending["next_call"] == requested["next_call"]
incomplete = repository_control.confirm_manual_lock({"base_id": "base", "request_id": requested["request_id"]})
@@ -494,6 +655,9 @@ def test_confirm_write_context_can_be_forwarded_under_repository_lock() -> None:
assert context["lock_session_id"] == "rlock-test"
assert context["repository_object"] == "Document.тл_Планировщик.Form.ФормаДокументаНовая"
assert context["layer_id"] == "base"
forwarded = adapter_1c_server.repository_write_context(context)
assert forwarded["layer_id"] == "base"
assert forwarded["lock_session_id"] == "rlock-test"
_context, conflict = adapter_1c_server.normalize_repository_write_context({
"lock_session_id": "rlock-one",