test(services): cover DSL import and plugin migration regressions (#36072)

Co-authored-by: WH-2099 <wh2099@pm.me>
This commit is contained in:
Nian 2026-07-07 23:31:04 +08:00 committed by GitHub
parent 5308b95aff
commit abd720146d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 64 additions and 23 deletions

View File

@ -416,10 +416,9 @@ class PluginMigration:
data = _tenant_plugin_adapter.validate_json(line)
tenant_id = data["tenant_id"]
plugin_ids = data["plugins"]
plugin_not_exist: list[str] = []
for plugin_id in plugin_ids:
if plugin_id not in package_identifier_by_plugin_id:
plugin_not_exist.append(plugin_id)
plugin_not_exist = [
plugin_id for plugin_id in plugin_ids if plugin_id not in package_identifier_by_plugin_id
]
if plugin_not_exist:
not_installed.append(

View File

@ -148,5 +148,35 @@ class TestHandlePluginInstanceInstall:
PluginMigration.install_plugins(str(extracted_plugins), str(output_file), workers=1)
assert json.loads(output_file.read_text())["not_installed"] == [
{"tenant_id": "tenant1", "plugin_not_exist": ["langgenius/missing"]}
{
"tenant_id": "tenant1",
"plugin_not_exist": ["langgenius/missing"],
}
]
mock_installer.install_from_identifiers.assert_called_once()
def test_install_plugins_skips_unresolved_plugins(self, tmp_path) -> None:
extracted_plugins = tmp_path / "plugins.jsonl"
output_file = tmp_path / "output.json"
extracted_plugins.write_text('{"tenant_id":"tenant1","plugins":["langgenius/missing"]}\n')
with (
patch(
f"{MIGRATION_MODULE}.PluginMigration.extract_unique_plugins",
return_value={
"plugins": {},
"plugin_not_exist": ["langgenius/missing"],
},
),
patch(f"{MIGRATION_MODULE}.PluginMigration.handle_plugin_instance_install", return_value={}),
patch(f"{MIGRATION_MODULE}.PluginInstaller") as mock_installer_cls,
):
mock_installer = MagicMock()
mock_installer.list_plugins.return_value = []
mock_installer_cls.return_value = mock_installer
PluginMigration.install_plugins(str(extracted_plugins), str(output_file), workers=1)
output = json.loads(output_file.read_text())
assert output["not_installed"] == [{"tenant_id": "tenant1", "plugin_not_exist": ["langgenius/missing"]}]
mock_installer.install_from_identifiers.assert_not_called()

View File

@ -633,6 +633,19 @@ def test_import_rag_pipeline_yaml_content_requires_content() -> None:
assert "yaml_content is required" in result.error
def test_import_rag_pipeline_rejects_oversized_yaml_content_before_parsing(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr("services.rag_pipeline.rag_pipeline_dsl_service.DSL_MAX_SIZE", 3)
service = RagPipelineDslService(session=Mock())
account = Mock(current_tenant_id="t1")
result = service.import_rag_pipeline(account=account, import_mode="yaml-content", yaml_content="你你")
assert result.status == ImportStatus.FAILED
assert result.error == "File size exceeds the limit of 10MB"
def test_import_rag_pipeline_yaml_content_requires_mapping() -> None:
service = RagPipelineDslService(session=Mock())
account = Mock(current_tenant_id="t1")

View File

@ -1,50 +1,49 @@
from types import SimpleNamespace
from unittest.mock import Mock
from services.app_dsl_service import AppDslService, ImportStatus
import pytest
from services.app_dsl_service import AppDslService
from services.entities.dsl_entities import ImportStatus
def test_import_app_rejects_oversized_yaml_content_by_bytes(monkeypatch) -> None:
monkeypatch.setattr("services.app_dsl_service.DSL_MAX_SIZE", 1)
service = AppDslService(session=SimpleNamespace())
def test_import_app_rejects_oversized_yaml_content_before_parsing(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr("services.app_dsl_service.DSL_MAX_SIZE", 3)
service = AppDslService(session=Mock())
account = Mock(current_tenant_id="tenant-1")
result = service.import_app(
account=SimpleNamespace(current_tenant_id="tenant-1"),
import_mode="yaml-content",
yaml_content="é",
)
result = service.import_app(account=account, import_mode="yaml-content", yaml_content="你你")
assert result.status == ImportStatus.FAILED
assert "10MB" in result.error
assert result.error == "File size exceeds the limit of 10MB"
def test_import_app_rejects_oversized_yaml_url_bytes_before_decode(monkeypatch) -> None:
def test_import_app_rejects_oversized_yaml_url_bytes_before_decode(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr("services.app_dsl_service.DSL_MAX_SIZE", 1)
response = Mock()
response.raise_for_status.return_value = None
response.content = b"\xff\xff"
monkeypatch.setattr("services.app_dsl_service.remote_fetcher.make_request", Mock(return_value=response))
service = AppDslService(session=SimpleNamespace())
service = AppDslService(session=Mock())
result = service.import_app(
account=SimpleNamespace(current_tenant_id="tenant-1"),
account=Mock(current_tenant_id="tenant-1"),
import_mode="yaml-url",
yaml_url="https://example.com/app.yaml",
)
assert result.status == ImportStatus.FAILED
assert "10MB" in result.error
assert result.error == "File size exceeds the limit of 10MB"
def test_import_app_returns_decode_error_for_invalid_yaml_url_bytes(monkeypatch) -> None:
def test_import_app_returns_decode_error_for_invalid_yaml_url_bytes(monkeypatch: pytest.MonkeyPatch) -> None:
response = Mock()
response.raise_for_status.return_value = None
response.content = b"\xff"
monkeypatch.setattr("services.app_dsl_service.remote_fetcher.make_request", Mock(return_value=response))
service = AppDslService(session=SimpleNamespace())
service = AppDslService(session=Mock())
result = service.import_app(
account=SimpleNamespace(current_tenant_id="tenant-1"),
account=Mock(current_tenant_id="tenant-1"),
import_mode="yaml-url",
yaml_url="https://example.com/app.yaml",
)