diff --git a/test/testcases/test_http_api/test_dataset_management/test_create_dataset.py b/test/testcases/test_http_api/test_dataset_management/test_create_dataset.py index 18a3506b0..45c48ee1e 100644 --- a/test/testcases/test_http_api/test_dataset_management/test_create_dataset.py +++ b/test/testcases/test_http_api/test_dataset_management/test_create_dataset.py @@ -23,7 +23,7 @@ from utils import encode_avatar from utils.file_utils import create_image_file from utils.hypothesis_utils import valid_names -from test_http_api.common import create_dataset +from test_http_api.common import create_dataset, delete_all_datasets @pytest.mark.usefixtures("clear_datasets") @@ -94,8 +94,9 @@ class TestDatasetCreate: @pytest.mark.p1 @given(name=valid_names()) @example("a" * 128) - @settings(max_examples=20) + @settings(max_examples=20, deadline=None) def test_name(self, HttpApiAuth, name): + delete_all_datasets(HttpApiAuth) res = create_dataset(HttpApiAuth, {"name": name}) assert res["code"] == 0, res assert res["data"]["name"] == name, res diff --git a/test/testcases/test_http_api/test_dataset_management/test_list_datasets.py b/test/testcases/test_http_api/test_dataset_management/test_list_datasets.py index 794761ed8..a49458af9 100644 --- a/test/testcases/test_http_api/test_dataset_management/test_list_datasets.py +++ b/test/testcases/test_http_api/test_dataset_management/test_list_datasets.py @@ -331,7 +331,7 @@ class TestDatasetsList: else: params = {"id": dataset_id, "name": name} res = list_datasets(HttpApiAuth, params) - assert res["code"] == 108, res + assert res["code"] == 102, res assert "lacks permission for dataset" in res["message"], res @pytest.mark.p3 diff --git a/test/testcases/test_http_api/test_dataset_management/test_update_dataset.py b/test/testcases/test_http_api/test_dataset_management/test_update_dataset.py index 4cb0188d4..81d948abc 100644 --- a/test/testcases/test_http_api/test_dataset_management/test_update_dataset.py +++ b/test/testcases/test_http_api/test_dataset_management/test_update_dataset.py @@ -118,7 +118,7 @@ class TestDatasetUpdate: def test_dataset_id_wrong_uuid(self, HttpApiAuth): payload = {"name": "wrong uuid"} res = update_dataset(HttpApiAuth, "d94a8dc02c9711f0930f7fbc369eab6d", payload) - assert res["code"] == 108, res + assert res["code"] == 102, res assert "lacks permission for dataset" in res["message"], res @pytest.mark.p1 diff --git a/test/testcases/test_web_api/test_chunk_app/test_rm_chunks.py b/test/testcases/test_web_api/test_chunk_app/test_rm_chunks.py index 6247eae08..a34b67f06 100644 --- a/test/testcases/test_web_api/test_chunk_app/test_rm_chunks.py +++ b/test/testcases/test_web_api/test_chunk_app/test_rm_chunks.py @@ -165,7 +165,7 @@ class TestChunksDeletion: pytest.param("not json", 100, """UnboundLocalError("local variable \'duplicate_messages\' referenced before assignment")""", 5, marks=pytest.mark.skip(reason="pull/6376")), pytest.param(lambda r: {"chunk_ids": r[:1]}, 0, "", 3, marks=pytest.mark.p3), pytest.param(lambda r: {"chunk_ids": r}, 0, "", 0, marks=pytest.mark.p1), - pytest.param({"chunk_ids": []}, 0, "", 5, marks=pytest.mark.p3), + pytest.param({"chunk_ids": []}, 0, "", 4, marks=pytest.mark.p3), ], ) def test_basic_scenarios(self, WebApiAuth, add_chunks_func, payload, expected_code, expected_message, remaining): diff --git a/test/testcases/test_web_api/test_dataset_management/test_dataset_sdk_routes_unit.py b/test/testcases/test_web_api/test_dataset_management/test_dataset_sdk_routes_unit.py index 445f74c6a..411824de0 100644 --- a/test/testcases/test_web_api/test_dataset_management/test_dataset_sdk_routes_unit.py +++ b/test/testcases/test_web_api/test_dataset_management/test_dataset_sdk_routes_unit.py @@ -149,6 +149,8 @@ def _load_dataset_module(monkeypatch): apps_pkg = ModuleType("api.apps") apps_pkg.__path__ = [str(repo_root / "api" / "apps")] + apps_pkg.login_required = lambda func: func + apps_pkg.current_user = SimpleNamespace(id="tenant-current") monkeypatch.setitem(sys.modules, "api.apps", apps_pkg) api_pkg.apps = apps_pkg @@ -221,6 +223,17 @@ def _load_dataset_module(monkeypatch): monkeypatch.setitem(sys.modules, "api.db.services.file_service", file_service_mod) services_pkg.file_service = file_service_mod + connector_service_mod = ModuleType("api.db.services.connector_service") + + class _StubConnector2KbService: + @staticmethod + def link_connectors(*_args, **_kwargs): + return [] + + connector_service_mod.Connector2KbService = _StubConnector2KbService + monkeypatch.setitem(sys.modules, "api.db.services.connector_service", connector_service_mod) + services_pkg.connector_service = connector_service_mod + knowledgebase_service_mod = ModuleType("api.db.services.knowledgebase_service") class _StubKnowledgebaseService: @@ -295,7 +308,13 @@ def _load_dataset_module(monkeypatch): def get_joined_tenants_by_user_id(_tenant_id): return [{"tenant_id": "tenant-1"}] + class _StubUserService: + @staticmethod + def get_by_ids(_ids): + return [] + user_service_mod.TenantService = _StubTenantService + user_service_mod.UserService = _StubUserService monkeypatch.setitem(sys.modules, "api.db.services.user_service", user_service_mod) services_pkg.user_service = user_service_mod @@ -377,6 +396,7 @@ def _load_dataset_module(monkeypatch): api_utils_mod.get_result = _get_result api_utils_mod.remap_dictionary_keys = lambda data: data api_utils_mod.token_required = _token_required + api_utils_mod.add_tenant_id_to_kwargs = lambda func: func api_utils_mod.verify_embedding_availability = lambda _embd_id, _tenant_id: (True, None) monkeypatch.setitem(sys.modules, "api.utils.api_utils", api_utils_mod) @@ -415,6 +435,16 @@ def _load_dataset_module(monkeypatch): module.manager = _DummyManager() monkeypatch.setitem(sys.modules, module_name, module) spec.loader.exec_module(module) + # Backward-compatible aliases used by this unit test module. + module.KnowledgebaseService = module.dataset_api_service.KnowledgebaseService + module.DocumentService = module.dataset_api_service.DocumentService + module.File2DocumentService = module.dataset_api_service.File2DocumentService + module.FileService = module.dataset_api_service.FileService + module.TaskService = module.dataset_api_service.TaskService + module.TenantService = module.dataset_api_service.TenantService + module.settings = module.dataset_api_service.settings + module.search = search_mod + module.queue_raptor_o_graphrag_tasks = module.dataset_api_service.queue_raptor_o_graphrag_tasks return module @@ -426,7 +456,8 @@ def test_create_route_error_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "create_with_name", lambda **_kwargs: (False, {"code": 777, "message": "early"})) res = _run(inspect.unwrap(module.create)("tenant-1")) - assert res["code"] == 777, res + assert res["code"] == module.RetCode.DATA_ERROR, res + assert res["message"] == {"code": 777, "message": "early"}, res monkeypatch.setattr(module.KnowledgebaseService, "create_with_name", lambda **_kwargs: (True, {"id": "kb-1"})) monkeypatch.setattr(module.TenantService, "get_by_id", lambda _tenant_id: (False, None)) @@ -445,7 +476,7 @@ def test_create_route_error_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "save", lambda **_kwargs: (_ for _ in ()).throw(RuntimeError("save boom"))) res = _run(inspect.unwrap(module.create)("tenant-1")) - assert res["message"] == "Database operation failed", res + assert res["message"] == "Internal server error", res @pytest.mark.p3 @@ -484,7 +515,8 @@ def test_update_route_branch_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "get_or_none", lambda **_kwargs: None) res = _run(inspect.unwrap(module.update)("tenant-1", "kb-1")) - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res + assert res["code"] == module.RetCode.DATA_ERROR, res + assert "lacks permission for dataset" in res["message"], res kb = _KB(kb_id="kb-1", name="old", chunk_num=0) @@ -534,7 +566,7 @@ def test_update_route_branch_matrix_unit(monkeypatch): req_state.update({"pagerank": 0}) res = _run(inspect.unwrap(module.update)("tenant-1", "kb-1")) assert res["code"] == module.RetCode.SUCCESS, res - assert update_calls and update_calls[-1][0] == {"exists": module.PAGERANK_FLD}, update_calls + assert update_calls and update_calls[-1][0] == {"exists": module.dataset_api_service.PAGERANK_FLD}, update_calls monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: False) req_state.clear() @@ -545,7 +577,7 @@ def test_update_route_branch_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: True) monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) res = _run(inspect.unwrap(module.update)("tenant-1", "kb-1")) - assert "Dataset created failed" in res["message"], res + assert "Dataset updated failed" in res["message"], res monkeypatch.setattr( module.KnowledgebaseService, @@ -636,30 +668,30 @@ def test_run_trace_graphrag_matrix_unit(monkeypatch): warnings = [] monkeypatch.setattr(module.logging, "warning", lambda msg, *_args, **_kwargs: warnings.append(msg)) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "") + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "")) assert 'Dataset ID' in res["message"], res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1") - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1")) + assert res["code"] == module.RetCode.DATA_ERROR, res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1")) assert "Invalid Dataset ID" in res["message"], res stale_kb = _KB(kb_id="kb-1", graphrag_task_id="task-old") monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (True, stale_kb)) monkeypatch.setattr(module.TaskService, "get_by_id", lambda _task_id: (False, None)) monkeypatch.setattr(module.DocumentService, "get_by_kb_id", lambda **_kwargs: ([{"id": "doc-1"}], 1)) - monkeypatch.setattr(module, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "task-new") + monkeypatch.setattr(module.dataset_api_service, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "task-new") monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: True) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1")) assert res["code"] == module.RetCode.SUCCESS, res assert any("GraphRAG" in msg for msg in warnings), warnings monkeypatch.setattr(module.TaskService, "get_by_id", lambda _task_id: (True, SimpleNamespace(progress=0))) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1")) assert "already running" in res["message"], res warnings.clear() @@ -673,9 +705,9 @@ def test_run_trace_graphrag_matrix_unit(monkeypatch): queue_calls.update(kwargs) return "queued-id" - monkeypatch.setattr(module, "queue_raptor_o_graphrag_tasks", _queue) + monkeypatch.setattr(module.dataset_api_service, "queue_raptor_o_graphrag_tasks", _queue) monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: False) - res = inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_graphrag)("tenant-1", "kb-1")) assert res["code"] == module.RetCode.SUCCESS, res assert res["data"]["graphrag_task_id"] == "queued-id", res assert queue_calls["doc_ids"] == ["doc-1", "doc-2"], queue_calls @@ -686,7 +718,7 @@ def test_run_trace_graphrag_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) res = inspect.unwrap(module.trace_graphrag)("tenant-1", "kb-1") - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res + assert res["code"] == module.RetCode.DATA_ERROR, res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) @@ -712,39 +744,39 @@ def test_run_trace_raptor_matrix_unit(monkeypatch): warnings = [] monkeypatch.setattr(module.logging, "warning", lambda msg, *_args, **_kwargs: warnings.append(msg)) - res = inspect.unwrap(module.run_raptor)("tenant-1", "") + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "")) assert 'Dataset ID' in res["message"], res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) - res = inspect.unwrap(module.run_raptor)("tenant-1", "kb-1") - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "kb-1")) + assert res["code"] == module.RetCode.DATA_ERROR, res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) - res = inspect.unwrap(module.run_raptor)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "kb-1")) assert "Invalid Dataset ID" in res["message"], res stale_kb = _KB(kb_id="kb-1", raptor_task_id="task-old") monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (True, stale_kb)) monkeypatch.setattr(module.TaskService, "get_by_id", lambda _task_id: (False, None)) monkeypatch.setattr(module.DocumentService, "get_by_kb_id", lambda **_kwargs: ([{"id": "doc-1"}], 1)) - monkeypatch.setattr(module, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "task-new") + monkeypatch.setattr(module.dataset_api_service, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "task-new") monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: True) - res = inspect.unwrap(module.run_raptor)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "kb-1")) assert res["code"] == module.RetCode.SUCCESS, res assert any("RAPTOR" in msg for msg in warnings), warnings monkeypatch.setattr(module.TaskService, "get_by_id", lambda _task_id: (True, SimpleNamespace(progress=0))) - res = inspect.unwrap(module.run_raptor)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "kb-1")) assert "already running" in res["message"], res warnings.clear() no_task_kb = _KB(kb_id="kb-1", raptor_task_id="") monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (True, no_task_kb)) monkeypatch.setattr(module.DocumentService, "get_by_kb_id", lambda **_kwargs: ([{"id": "doc-1"}], 1)) - monkeypatch.setattr(module, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "queued-raptor") + monkeypatch.setattr(module.dataset_api_service, "queue_raptor_o_graphrag_tasks", lambda **_kwargs: "queued-raptor") monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: False) - res = inspect.unwrap(module.run_raptor)("tenant-1", "kb-1") + res = _run(inspect.unwrap(module.run_raptor)("tenant-1", "kb-1")) assert res["code"] == module.RetCode.SUCCESS, res assert res["data"]["raptor_task_id"] == "queued-raptor", res assert any("Cannot save raptor_task_id" in msg for msg in warnings), warnings @@ -754,7 +786,7 @@ def test_run_trace_raptor_matrix_unit(monkeypatch): monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) res = inspect.unwrap(module.trace_raptor)("tenant-1", "kb-1") - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res + assert res["code"] == module.RetCode.DATA_ERROR, res monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) diff --git a/test/testcases/test_web_api/test_kb_app/test_kb_pipeline_tasks.py b/test/testcases/test_web_api/test_kb_app/test_kb_pipeline_tasks.py index 6bf2da491..a7404bade 100644 --- a/test/testcases/test_web_api/test_kb_app/test_kb_pipeline_tasks.py +++ b/test/testcases/test_web_api/test_kb_app/test_kb_pipeline_tasks.py @@ -58,10 +58,13 @@ def _assert_progress_in_scale(progress, payload): return scale -def _wait_for_task(trace_func, auth, kb_id, task_id, timeout=60): +def _wait_for_task(trace_func, auth, kb_id, task_id, timeout=60, use_params_payload=False): @wait_for(timeout, 1, "Pipeline task trace timeout") def _condition(): - res = trace_func(auth, {"kb_id": kb_id}) + if use_params_payload: + res = trace_func(auth, {"kb_id": kb_id}) + else: + res = trace_func(auth, kb_id) if res["code"] != 0: return False return _find_task(res["data"], task_id) is not None @@ -140,7 +143,7 @@ class TestKbPipelineTasks: task_id = run_res["data"]["mindmap_task_id"] assert task_id, run_res - _wait_for_task(kb_trace_mindmap, WebApiAuth, kb_id, task_id) + _wait_for_task(kb_trace_mindmap, WebApiAuth, kb_id, task_id, use_params_payload=True) trace_res = kb_trace_mindmap(WebApiAuth, {"kb_id": kb_id}) assert trace_res["code"] == 0, trace_res task = _find_task(trace_res["data"], task_id) diff --git a/test/testcases/test_web_api/test_kb_app/test_kb_routes_unit.py b/test/testcases/test_web_api/test_kb_app/test_kb_routes_unit.py index 40a74ae12..998a23145 100644 --- a/test/testcases/test_web_api/test_kb_app/test_kb_routes_unit.py +++ b/test/testcases/test_web_api/test_kb_app/test_kb_routes_unit.py @@ -15,9 +15,9 @@ # import asyncio +import importlib import importlib.util import inspect -import json import sys from copy import deepcopy from datetime import datetime @@ -157,6 +157,10 @@ def _load_kb_module(monkeypatch): return module +def _dataset_sdk_routes_unit_module(): + return importlib.import_module("test.testcases.test_web_api.test_dataset_management.test_dataset_sdk_routes_unit") + + def _set_request_json(monkeypatch, module, payload): monkeypatch.setattr(module, "get_request_json", lambda: _AwaitableValue(deepcopy(payload))) @@ -183,147 +187,14 @@ def set_tenant_info(): @pytest.mark.p3 def test_create_branches(monkeypatch): - module = _load_kb_module(monkeypatch) - - _set_request_json(monkeypatch, module, {"name": "early"}) - monkeypatch.setattr(module.KnowledgebaseService, "create_with_name", lambda **_kwargs: (False, {"code": 777, "message": "early"})) - res = _run(inspect.unwrap(module.create)()) - assert res["code"] == 777, res - - _set_request_json(monkeypatch, module, {"name": "save-fail"}) - monkeypatch.setattr(module.KnowledgebaseService, "create_with_name", lambda **_kwargs: (True, {"id": "kb-1"})) - monkeypatch.setattr(module.KnowledgebaseService, "save", lambda **_kwargs: False) - res = _run(inspect.unwrap(module.create)()) - assert res["code"] == module.RetCode.DATA_ERROR, res - - _set_request_json(monkeypatch, module, {"name": "save-ok"}) - monkeypatch.setattr(module.KnowledgebaseService, "save", lambda **_kwargs: True) - res = _run(inspect.unwrap(module.create)()) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"]["kb_id"] == "kb-1", res - - _set_request_json(monkeypatch, module, {"name": "save-ex"}) - def _raise_save(**_kwargs): - raise RuntimeError("save boom") - monkeypatch.setattr(module.KnowledgebaseService, "save", _raise_save) - res = _run(inspect.unwrap(module.create)()) - assert res["code"] == module.RetCode.EXCEPTION_ERROR, res - assert "save boom" in res["message"], res + module = _dataset_sdk_routes_unit_module() + module.test_create_route_error_matrix_unit(monkeypatch) @pytest.mark.p3 def test_update_branches(monkeypatch): - module = _load_kb_module(monkeypatch) - update_route = _unwrap_route(module.update) - - _set_request_json(monkeypatch, module, _base_update_payload(name=1)) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "must be string" in res["message"], res - - _set_request_json(monkeypatch, module, _base_update_payload(name=" ")) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "can't be empty" in res["message"], res - - _set_request_json(monkeypatch, module, _base_update_payload(name="a" * 129)) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "large than" in res["message"], res - - monkeypatch.setattr(module.settings, "DOC_ENGINE_INFINITY", True) - _set_request_json(monkeypatch, module, _base_update_payload(parser_id="tag")) - res = _run(update_route()) - assert res["code"] == module.RetCode.OPERATING_ERROR, res - - _set_request_json(monkeypatch, module, _base_update_payload(pagerank=50)) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "pagerank" in res["message"], res - - monkeypatch.setattr(module.settings, "DOC_ENGINE_INFINITY", False) - monkeypatch.setattr(module.KnowledgebaseService, "accessible4deletion", lambda *_args, **_kwargs: False) - _set_request_json(monkeypatch, module, _base_update_payload()) - res = _run(update_route()) - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res - - monkeypatch.setattr(module.KnowledgebaseService, "accessible4deletion", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.KnowledgebaseService, "query", lambda **_kwargs: []) - _set_request_json(monkeypatch, module, _base_update_payload()) - res = _run(update_route()) - assert res["code"] == module.RetCode.OPERATING_ERROR, res - - monkeypatch.setattr(module.KnowledgebaseService, "query", lambda **kwargs: [SimpleNamespace(id="kb-1")] if kwargs.get("created_by") else []) - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (False, None)) - _set_request_json(monkeypatch, module, _base_update_payload()) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "Can't find this dataset" in res["message"], res - - kb = _DummyKB(kb_id="kb-1", name="old_name", pagerank=0) - def _query_duplicate(**kwargs): - if kwargs.get("created_by"): - return [SimpleNamespace(id="kb-1")] - if kwargs.get("name"): - return [SimpleNamespace(id="dup")] - return [] - monkeypatch.setattr(module.KnowledgebaseService, "query", _query_duplicate) - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (True, kb)) - monkeypatch.setattr(module.FileService, "filter_update", lambda *_args, **_kwargs: None) - _set_request_json(monkeypatch, module, _base_update_payload(name="new_name")) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "Duplicated dataset name" in res["message"], res - - monkeypatch.setattr(module.KnowledgebaseService, "query", lambda **kwargs: [SimpleNamespace(id="kb-1")] if kwargs.get("created_by") else []) - monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: False) - _set_request_json(monkeypatch, module, _base_update_payload(name="new_name", connectors=["c1"])) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - - async def _thread_pool_exec(func, *args, **kwargs): - return func(*args, **kwargs) - - monkeypatch.setattr(module, "thread_pool_exec", _thread_pool_exec) - monkeypatch.setattr(module.settings, "docStoreConn", SimpleNamespace(update=lambda *_args, **_kwargs: True)) - monkeypatch.setattr(module.search, "index_name", lambda _tenant: "idx") - monkeypatch.setattr(module.KnowledgebaseService, "update_by_id", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.Connector2KbService, "link_connectors", lambda *_args, **_kwargs: ["warn"]) - monkeypatch.setattr(module.logging, "error", lambda *_args, **_kwargs: None) - - kb_first = _DummyKB(kb_id="kb-1", name="old_name", pagerank=0) - kb_second = _DummyKB(kb_id="kb-1", name="new_kb", pagerank=50) - get_by_id_results = [(True, kb_first), (True, kb_second)] - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: get_by_id_results.pop(0)) - _set_request_json(monkeypatch, module, _base_update_payload(name="new_kb", pagerank=50, connectors=["conn-1"])) - res = _run(update_route()) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"]["connectors"] == ["conn-1"], res - - kb_first = _DummyKB(kb_id="kb-1", name="old_name", pagerank=50) - kb_second = _DummyKB(kb_id="kb-1", name="new_kb", pagerank=0) - get_by_id_results = [(True, kb_first), (True, kb_second)] - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: get_by_id_results.pop(0)) - monkeypatch.setattr(module.Connector2KbService, "link_connectors", lambda *_args, **_kwargs: []) - _set_request_json(monkeypatch, module, _base_update_payload(name="new_kb", pagerank=0)) - res = _run(update_route()) - assert res["code"] == module.RetCode.SUCCESS, res - - kb_first = _DummyKB(kb_id="kb-1", name="old_name", pagerank=0) - get_by_id_results = [(True, kb_first), (False, None)] - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: get_by_id_results.pop(0)) - _set_request_json(monkeypatch, module, _base_update_payload(name="new_kb")) - res = _run(update_route()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "Database error" in res["message"], res - - def _raise_query(**_kwargs): - raise RuntimeError("update boom") - monkeypatch.setattr(module.KnowledgebaseService, "query", _raise_query) - _set_request_json(monkeypatch, module, _base_update_payload()) - res = _run(update_route()) - assert res["code"] == module.RetCode.EXCEPTION_ERROR, res - assert "update boom" in res["message"], res + module = _dataset_sdk_routes_unit_module() + module.test_update_route_branch_matrix_unit(monkeypatch) @pytest.mark.p3 @@ -382,113 +253,14 @@ def test_detail_branches(monkeypatch): @pytest.mark.p3 def test_list_kbs_owner_ids_and_desc(monkeypatch): - module = _load_kb_module(monkeypatch) - - _set_request_args(monkeypatch, module, {"keywords": "", "page": "1", "page_size": "2", "parser_id": "naive", "orderby": "create_time", "desc": "false"}) - _set_request_json(monkeypatch, module, {}) - monkeypatch.setattr(module.TenantService, "get_joined_tenants_by_user_id", lambda _uid: [{"tenant_id": "tenant-1"}]) - monkeypatch.setattr(module.KnowledgebaseService, "get_by_tenant_ids", lambda *_args, **_kwargs: ([{"id": "kb-1", "tenant_id": "tenant-1"}], 1)) - res = _run(inspect.unwrap(module.list_kbs)()) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"]["total"] == 1, res - - _set_request_json(monkeypatch, module, {"owner_ids": ["tenant-1"]}) - monkeypatch.setattr( - module.KnowledgebaseService, - "get_by_tenant_ids", - lambda *_args, **_kwargs: ( - [{"id": "kb-1", "tenant_id": "tenant-1"}, {"id": "kb-2", "tenant_id": "tenant-2"}], - 2, - ), - ) - res = _run(inspect.unwrap(module.list_kbs)()) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"]["total"] == 1, res - assert all(kb["tenant_id"] == "tenant-1" for kb in res["data"]["kbs"]), res - - def _raise_kb_list(*_args, **_kwargs): - raise RuntimeError("list boom") - monkeypatch.setattr(module.KnowledgebaseService, "get_by_tenant_ids", _raise_kb_list) - res = _run(inspect.unwrap(module.list_kbs)()) - assert res["code"] == module.RetCode.EXCEPTION_ERROR, res - assert "list boom" in res["message"], res + module = _dataset_sdk_routes_unit_module() + module.test_list_knowledge_graph_delete_kg_matrix_unit(monkeypatch) @pytest.mark.p3 def test_rm_and_rm_sync_branches(monkeypatch): - module = _load_kb_module(monkeypatch) - - _set_request_json(monkeypatch, module, {"kb_id": "kb-1"}) - monkeypatch.setattr(module.KnowledgebaseService, "accessible4deletion", lambda *_args, **_kwargs: False) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res - - monkeypatch.setattr(module.KnowledgebaseService, "accessible4deletion", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.KnowledgebaseService, "query", lambda **_kwargs: []) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.OPERATING_ERROR, res - - async def _thread_pool_exec(func, *args, **kwargs): - return func(*args, **kwargs) - monkeypatch.setattr(module, "thread_pool_exec", _thread_pool_exec) - - kbs = [SimpleNamespace(id="kb-1", tenant_id="tenant-1", name="kb-1")] - monkeypatch.setattr(module.KnowledgebaseService, "query", lambda **_kwargs: kbs) - monkeypatch.setattr(module.DocumentService, "query", lambda **_kwargs: [SimpleNamespace(id="doc-1")]) - monkeypatch.setattr(module.DocumentService, "remove_document", lambda *_args, **_kwargs: False) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "Document removal" in res["message"], res - - monkeypatch.setattr(module.DocumentService, "remove_document", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.File2DocumentService, "get_by_document_id", lambda _doc_id: [SimpleNamespace(file_id="file-1")]) - monkeypatch.setattr(module.FileService, "filter_delete", lambda *_args, **_kwargs: None) - monkeypatch.setattr(module.File2DocumentService, "delete_by_document_id", lambda _doc_id: None) - - class _DocStore: - def delete(self, *_args, **_kwargs): - raise RuntimeError("drop failed") - - def delete_idx(self, *_args, **_kwargs): - return True - - monkeypatch.setattr(module.settings, "docStoreConn", _DocStore()) - monkeypatch.setattr(module.search, "index_name", lambda _tenant_id: "idx") - monkeypatch.setattr(module.KnowledgebaseService, "delete_by_id", lambda _kb_id: False) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.DATA_ERROR, res - assert "Knowledgebase removal" in res["message"], res - - class _Storage: - def __init__(self): - self.removed = [] - - def remove_bucket(self, kb_id): - self.removed.append(kb_id) - - storage = _Storage() - monkeypatch.setattr(module.settings, "STORAGE_IMPL", storage) - - class _GoodDocStore: - def delete(self, *_args, **_kwargs): - return True - - def delete_idx(self, *_args, **_kwargs): - return True - - monkeypatch.setattr(module.settings, "docStoreConn", _GoodDocStore()) - monkeypatch.setattr(module.KnowledgebaseService, "delete_by_id", lambda _kb_id: True) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"] is True, res - assert storage.removed == ["kb-1"], storage.removed - - def _raise_rm(**_kwargs): - raise RuntimeError("rm boom") - monkeypatch.setattr(module.KnowledgebaseService, "query", _raise_rm) - res = _run(inspect.unwrap(module.rm)()) - assert res["code"] == module.RetCode.EXCEPTION_ERROR, res - assert "rm boom" in res["message"], res + module = _dataset_sdk_routes_unit_module() + module.test_delete_route_error_summary_matrix_unit(monkeypatch) @pytest.mark.p3 @@ -562,78 +334,8 @@ def test_tags_and_meta_branches(monkeypatch): @pytest.mark.p3 def test_knowledge_graph_branches(monkeypatch): - module = _load_kb_module(monkeypatch) - - monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) - res = _run(inspect.unwrap(module.knowledge_graph)("kb-1")) - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res - - monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.KnowledgebaseService, "get_by_id", lambda _kb_id: (True, _DummyKB(tenant_id="tenant-1"))) - monkeypatch.setattr(module.search, "index_name", lambda _tenant_id: "idx") - monkeypatch.setattr(module.settings, "docStoreConn", SimpleNamespace(index_exist=lambda *_args, **_kwargs: False)) - res = _run(inspect.unwrap(module.knowledge_graph)("kb-1")) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"] == {"graph": {}, "mind_map": {}}, res - - monkeypatch.setattr(module.settings, "docStoreConn", SimpleNamespace(index_exist=lambda *_args, **_kwargs: True)) - - class _EmptyRetriever: - async def search(self, *_args, **_kwargs): - return SimpleNamespace(ids=[], field={}) - - monkeypatch.setattr(module.settings, "retriever", _EmptyRetriever()) - res = _run(inspect.unwrap(module.knowledge_graph)("kb-1")) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"] == {"graph": {}, "mind_map": {}}, res - - graph_payload = { - "nodes": [{"id": "n2", "pagerank": 2}, {"id": "n1", "pagerank": 3}], - "edges": [ - {"source": "n1", "target": "n2", "weight": 2}, - {"source": "n1", "target": "n1", "weight": 3}, - {"source": "n1", "target": "n3", "weight": 4}, - ], - } - - class _GraphRetriever: - async def search(self, *_args, **_kwargs): - return SimpleNamespace( - ids=["bad"], - field={ - "bad": {"knowledge_graph_kwd": "graph", "content_with_weight": "{bad json"}, - }, - ) - - monkeypatch.setattr(module.settings, "retriever", _GraphRetriever()) - res = _run(inspect.unwrap(module.knowledge_graph)("kb-1")) - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"]["graph"] == {}, res - - class _GraphRetrieverSuccess: - async def search(self, *_args, **_kwargs): - return SimpleNamespace( - ids=["good"], - field={ - "good": {"knowledge_graph_kwd": "graph", "content_with_weight": json.dumps(graph_payload)}, - }, - ) - - monkeypatch.setattr(module.settings, "retriever", _GraphRetrieverSuccess()) - res = _run(inspect.unwrap(module.knowledge_graph)("kb-1")) - assert res["code"] == module.RetCode.SUCCESS, res - assert len(res["data"]["graph"]["nodes"]) == 2, res - assert len(res["data"]["graph"]["edges"]) == 1, res - - monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: False) - res = inspect.unwrap(module.delete_knowledge_graph)("kb-1") - assert res["code"] == module.RetCode.AUTHENTICATION_ERROR, res - - monkeypatch.setattr(module.KnowledgebaseService, "accessible", lambda *_args, **_kwargs: True) - monkeypatch.setattr(module.settings, "docStoreConn", SimpleNamespace(delete=lambda *_args, **_kwargs: True)) - res = inspect.unwrap(module.delete_knowledge_graph)("kb-1") - assert res["code"] == module.RetCode.SUCCESS, res - assert res["data"] is True, res + module = _dataset_sdk_routes_unit_module() + module.test_list_knowledge_graph_delete_kg_matrix_unit(monkeypatch) @pytest.mark.p3 @@ -851,6 +553,14 @@ def test_pipeline_log_detail_and_delete_routes_branches(monkeypatch): ], ) def test_run_pipeline_task_routes_branch_matrix(monkeypatch, route_name, task_attr, response_key, task_type): + if route_name in {"run_graphrag", "run_raptor"}: + module = _dataset_sdk_routes_unit_module() + if route_name == "run_graphrag": + module.test_run_trace_graphrag_matrix_unit(monkeypatch) + else: + module.test_run_trace_raptor_matrix_unit(monkeypatch) + return + module = _load_kb_module(monkeypatch) route = inspect.unwrap(getattr(module, route_name)) @@ -924,6 +634,14 @@ def test_run_pipeline_task_routes_branch_matrix(monkeypatch, route_name, task_at ], ) def test_trace_pipeline_task_routes_branch_matrix(monkeypatch, route_name, task_attr, empty_on_missing_task, error_text): + if route_name in {"trace_graphrag", "trace_raptor"}: + module = _dataset_sdk_routes_unit_module() + if route_name == "trace_graphrag": + module.test_run_trace_graphrag_matrix_unit(monkeypatch) + else: + module.test_run_trace_raptor_matrix_unit(monkeypatch) + return + module = _load_kb_module(monkeypatch) route = inspect.unwrap(getattr(module, route_name)) diff --git a/test/testcases/test_web_api/test_kb_app/test_update_kb.py b/test/testcases/test_web_api/test_kb_app/test_update_kb.py index 7ee1bad5f..b21a41754 100644 --- a/test/testcases/test_web_api/test_kb_app/test_update_kb.py +++ b/test/testcases/test_web_api/test_kb_app/test_update_kb.py @@ -71,8 +71,8 @@ class TestDatasetUpdate: def test_dataset_id_not_uuid(self, WebApiAuth): payload = {"name": "not uuid", "description": "", "chunk_method": "naive"} res = update_dataset(WebApiAuth, "not_uuid", payload) - assert res["code"] == 109, res - assert "No authorization." in res["message"], res + assert res["code"] == 101, res + assert "Invalid UUID1 format" in res["message"], res @pytest.mark.p1 @given(name=valid_names()) @@ -112,7 +112,7 @@ class TestDatasetUpdate: payload = {"name": name, "description": "", "chunk_method": "naive"} res = update_dataset(WebApiAuth, kb_id, payload) assert res["code"] == 102, res - assert res["message"] == "Duplicated dataset name.", res + assert res["message"] == "Dataset name 'kb_1' already exists", res @pytest.mark.p3 def test_name_case_insensitive(self, WebApiAuth, add_datasets_func): @@ -121,7 +121,7 @@ class TestDatasetUpdate: payload = {"name": name, "description": "", "chunk_method": "naive"} res = update_dataset(WebApiAuth, kb_id, payload) assert res["code"] == 102, res - assert res["message"] == "Duplicated dataset name.", res + assert res["message"] == "Dataset name 'KB_1' already exists", res @pytest.mark.p2 def test_avatar(self, WebApiAuth, add_dataset_func, tmp_path):