from __future__ import annotations import importlib.util from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[2] CONNECTOR = ROOT / "plugins" / "1c" / "connector" def load_adapter(): path = CONNECTOR / "adapter_1c_server.py" spec = importlib.util.spec_from_file_location("adapter_1c_policy_test", path) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def test_sql_base_access_policy_contract() -> None: policy = yaml.safe_load((CONNECTOR / "policies" / "sql-base-access-policy.yaml").read_text(encoding="utf-8")) assert policy["status"] == "active" assert policy["base_settings"]["selector"] == "base_id" assert set(policy["base_settings"]["required_fields"]) == {"server", "database", "user"} assert policy["read_scope"]["application_data"] == "read_only" assert policy["read_scope"]["metadata_structure"] == "read_only" assert set(policy["write_scope"]["allowed"].values()) == {"ConfigSave", "ConfigCASSave"} assert policy["sql_identity_management"]["mode"] == "forbidden" def test_xml_is_offline_decoder_evidence_and_runtime_is_sql_only() -> None: policy = yaml.safe_load((CONNECTOR / "policies" / "xml-decoding-reference-policy.yaml").read_text(encoding="utf-8")) service = yaml.safe_load((CONNECTOR / "service.yaml").read_text(encoding="utf-8")) assert policy["status"] == "active" assert policy["offline_analysis"]["allowed"] is True assert policy["runtime"]["source"] == "sql_only" assert policy["runtime"]["xml_mount_required"] is False assert "policies/xml-decoding-reference-policy.yaml" in service["contracts"]["policies"] def test_designer_sql_decoding_policy_keeps_adapter_read_only() -> None: policy = yaml.safe_load((CONNECTOR / "policies" / "designer-sql-decoding-policy.yaml").read_text(encoding="utf-8")) service = yaml.safe_load((CONNECTOR / "service.yaml").read_text(encoding="utf-8")) assert policy["scope"]["default_base_id"] == "upo_test" assert policy["scope"]["adapter_role"] == "sql_observer_and_decoder" assert policy["credentials"]["persistence"] == "forbidden_in_repository" assert policy["sql_observation"]["adapter_access"] == "read_only" assert "direct_application_data_write" in policy["sql_observation"]["forbidden"] assert policy["xml"]["role"] == "offline_schema_reference_only" assert "policies/designer-sql-decoding-policy.yaml" in service["contracts"]["policies"] def test_runtime_rejects_xml_sources_at_any_payload_depth() -> None: adapter = load_adapter() direct = adapter.call_method_impl( "metadata.object.get", {"base_id": "upo_test", "ref": "Catalog.Test", "xml_path": "Configuration.xml"}, ) nested = adapter.call_method_impl( "metadata.write.plan", {"base_id": "upo_test", "target": {"form_xml_path": "Forms/Test/Ext/Form.xml"}}, ) assert direct["status"] == "invalid_argument" assert direct["argument"] == "payload.xml_path" assert nested["status"] == "invalid_argument" assert nested["argument"] == "payload.target.form_xml_path" assert "SQL-only" in direct["diagnostics"]["message"] def test_adapter_has_no_xml_runtime_environment_configuration() -> None: source = (CONNECTOR / "adapter_1c_server.py").read_text(encoding="utf-8") assert "ONEC_XML" not in source def test_sql_connection_requires_explicit_base_entry(monkeypatch) -> None: adapter = load_adapter() for name in ( "ONEC_SQL_BASES_JSON", "ONEC_SQL_CONNECTIONS_JSON", "ONEC_SQL_BASES_JSON_FILE", "ONEC_SQL_CONNECTIONS_JSON_FILE", ): monkeypatch.delenv(name, raising=False) monkeypatch.setenv("ONEC_SQL_SERVER", "must-not-be-used") monkeypatch.setenv("ONEC_SQL_USER", "must-not-be-used") monkeypatch.setenv("ONEC_SQL_PASSWORD", "must-not-be-used") config, error = adapter.sql_config_for_base("upo_test") assert config is None assert error and error["status"] == "not_configured" def test_sql_connection_does_not_infer_database_name(monkeypatch) -> None: adapter = load_adapter() monkeypatch.setenv( "ONEC_SQL_BASES_JSON", '{"upo_test":{"server":"sql-host","user":"login","password":"secret"}}', ) config, error = adapter.sql_config_for_base("upo_test") assert config is None assert error and "database" in error["message"] def test_sql_connection_ignores_legacy_connection_map(monkeypatch) -> None: adapter = load_adapter() monkeypatch.delenv("ONEC_SQL_BASES_JSON", raising=False) monkeypatch.delenv("ONEC_SQL_BASES_JSON_FILE", raising=False) monkeypatch.setenv( "ONEC_SQL_CONNECTIONS_JSON", '{"upo_test":{"server":"must-not-be-used","database":"must-not-be-used","user":"must-not-be-used","password":"must-not-be-used"}}', ) config, error = adapter.sql_config_for_base("upo_test") assert config is None assert error and error["status"] == "not_configured" assert adapter.sql_configured_base_ids() == []