diff --git a/sdk/python/test/test_http_api/common.py b/sdk/python/test/test_http_api/common.py index b0eca8988..c0e84281a 100644 --- a/sdk/python/test/test_http_api/common.py +++ b/sdk/python/test/test_http_api/common.py @@ -28,11 +28,14 @@ FILE_API_URL = "/api/v1/datasets/{dataset_id}/documents" FILE_CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/chunks" CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/documents/{document_id}/chunks" CHAT_ASSISTANT_API_URL = "/api/v1/chats" +SESSION_WITH_CHAT_ASSISTANT_API_URL = "/api/v1/chats/{chat_id}/sessions" +SESSION_WITH_AGENT_API_URL = "/api/v1/agents/{agent_id}/sessions" INVALID_API_TOKEN = "invalid_key_123" DATASET_NAME_LIMIT = 128 DOCUMENT_NAME_LIMIT = 128 -CHAT_ASSISTANT_LIMIT = 255 +CHAT_ASSISTANT_NAME_LIMIT = 255 +SESSION_WITH_CHAT_NAME_LIMIT = 255 # DATASET MANAGEMENT @@ -219,3 +222,28 @@ def batch_create_chat_assistants(auth, num): res = create_chat_assistant(auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": []}) chat_assistant_ids.append(res["data"]["id"]) return chat_assistant_ids + + +# SESSION MANAGEMENT +def create_session_with_chat_assistant(auth, chat_assistant_id, payload=None): + url = f"{HOST_ADDRESS}{SESSION_WITH_CHAT_ASSISTANT_API_URL}".format(chat_id=chat_assistant_id) + res = requests.post(url=url, headers=HEADERS, auth=auth, json=payload) + return res.json() + + +def list_session_with_chat_assistants(auth, chat_assistant_id, params=None): + url = f"{HOST_ADDRESS}{SESSION_WITH_CHAT_ASSISTANT_API_URL}".format(chat_id=chat_assistant_id) + res = requests.get(url=url, headers=HEADERS, auth=auth, params=params) + return res.json() + + +def update_session_with_chat_assistant(auth, chat_assistant_id, session_id, payload=None): + url = f"{HOST_ADDRESS}{SESSION_WITH_CHAT_ASSISTANT_API_URL}/{session_id}".format(chat_id=chat_assistant_id) + res = requests.put(url=url, headers=HEADERS, auth=auth, json=payload) + return res.json() + + +def delete_session_with_chat_assistants(auth, chat_assistant_id, payload=None): + url = f"{HOST_ADDRESS}{SESSION_WITH_CHAT_ASSISTANT_API_URL}".format(chat_id=chat_assistant_id) + res = requests.delete(url=url, headers=HEADERS, auth=auth, json=payload) + return res.json() diff --git a/sdk/python/test/test_http_api/conftest.py b/sdk/python/test/test_http_api/conftest.py index 37770b545..5eea9f651 100644 --- a/sdk/python/test/test_http_api/conftest.py +++ b/sdk/python/test/test_http_api/conftest.py @@ -15,7 +15,17 @@ # import pytest -from common import add_chunk, batch_create_datasets, bulk_upload_documents, delete_chat_assistants, delete_datasets, list_documnets, parse_documnets +from common import ( + add_chunk, + batch_create_datasets, + bulk_upload_documents, + create_chat_assistant, + delete_chat_assistants, + delete_datasets, + delete_session_with_chat_assistants, + list_documnets, + parse_documnets, +) from libs.utils import wait_for from libs.utils.file_utils import ( create_docx_file, @@ -41,15 +51,30 @@ def condition(_auth, _dataset_id): @pytest.fixture(scope="function") -def clear_datasets(get_http_api_auth): - yield - delete_datasets(get_http_api_auth) +def clear_datasets(request, get_http_api_auth): + def cleanup(): + delete_datasets(get_http_api_auth) + + request.addfinalizer(cleanup) @pytest.fixture(scope="function") -def clear_chat_assistants(get_http_api_auth): - yield - delete_chat_assistants(get_http_api_auth) +def clear_chat_assistants(request, get_http_api_auth): + def cleanup(): + delete_chat_assistants(get_http_api_auth) + + request.addfinalizer(cleanup) + + +@pytest.fixture(scope="function") +def clear_session_with_chat_assistants(request, get_http_api_auth, add_chat_assistants): + _, _, chat_assistant_ids = add_chat_assistants + + def cleanup(): + for chat_assistant_id in chat_assistant_ids: + delete_session_with_chat_assistants(get_http_api_auth, chat_assistant_id) + + request.addfinalizer(cleanup) @pytest.fixture @@ -126,3 +151,22 @@ def add_chunks(get_http_api_auth, add_document): sleep(1) return dataset_id, document_id, chunk_ids + + +@pytest.fixture(scope="class") +def add_chat_assistants(request, get_http_api_auth, add_document): + def cleanup(): + delete_chat_assistants(get_http_api_auth) + + request.addfinalizer(cleanup) + + dataset_id, document_id = add_document + parse_documnets(get_http_api_auth, dataset_id, {"document_ids": [document_id]}) + condition(get_http_api_auth, dataset_id) + + chat_assistant_ids = [] + for i in range(5): + res = create_chat_assistant(get_http_api_auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": [dataset_id]}) + chat_assistant_ids.append(res["data"]["id"]) + + return dataset_id, document_id, chat_assistant_ids diff --git a/sdk/python/test/test_http_api/test_chat_assistant_management/conftest.py b/sdk/python/test/test_http_api/test_chat_assistant_management/conftest.py index 111b7dd7c..9265b3aef 100644 --- a/sdk/python/test/test_http_api/test_chat_assistant_management/conftest.py +++ b/sdk/python/test/test_http_api/test_chat_assistant_management/conftest.py @@ -14,36 +14,33 @@ # limitations under the License. # import pytest -from common import create_chat_assistant, delete_chat_assistants +from common import create_chat_assistant, delete_chat_assistants, list_documnets, parse_documnets +from libs.utils import wait_for -@pytest.fixture(scope="class") -def add_chat_assistants(request, get_http_api_auth, add_chunks): - def cleanup(): - delete_chat_assistants(get_http_api_auth) - - request.addfinalizer(cleanup) - - dataset_id, document_id, chunk_ids = add_chunks - chat_assistant_ids = [] - for i in range(5): - res = create_chat_assistant(get_http_api_auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": [dataset_id]}) - chat_assistant_ids.append(res["data"]["id"]) - - return dataset_id, document_id, chunk_ids, chat_assistant_ids +@wait_for(30, 1, "Document parsing timeout") +def condition(_auth, _dataset_id): + res = list_documnets(_auth, _dataset_id) + for doc in res["data"]["docs"]: + if doc["run"] != "DONE": + return False + return True @pytest.fixture(scope="function") -def add_chat_assistants_func(request, get_http_api_auth, add_chunks): +def add_chat_assistants_func(request, get_http_api_auth, add_document): def cleanup(): delete_chat_assistants(get_http_api_auth) request.addfinalizer(cleanup) - dataset_id, document_id, chunk_ids = add_chunks + dataset_id, document_id = add_document + parse_documnets(get_http_api_auth, dataset_id, {"document_ids": [document_id]}) + condition(get_http_api_auth, dataset_id) + chat_assistant_ids = [] for i in range(5): res = create_chat_assistant(get_http_api_auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": [dataset_id]}) chat_assistant_ids.append(res["data"]["id"]) - return dataset_id, document_id, chunk_ids, chat_assistant_ids + return dataset_id, document_id, chat_assistant_ids diff --git a/sdk/python/test/test_http_api/test_chat_assistant_management/test_create_chat_assistant.py b/sdk/python/test/test_http_api/test_chat_assistant_management/test_create_chat_assistant.py index ed7cb96b7..4ed6c9a69 100644 --- a/sdk/python/test/test_http_api/test_chat_assistant_management/test_create_chat_assistant.py +++ b/sdk/python/test/test_http_api/test_chat_assistant_management/test_create_chat_assistant.py @@ -15,7 +15,7 @@ # import pytest -from common import CHAT_ASSISTANT_LIMIT, INVALID_API_TOKEN, create_chat_assistant +from common import CHAT_ASSISTANT_NAME_LIMIT, INVALID_API_TOKEN, create_chat_assistant from libs.auth import RAGFlowHttpApiAuth from libs.utils import encode_avatar from libs.utils.file_utils import create_image_file @@ -46,7 +46,7 @@ class TestChatAssistantCreate: "payload, expected_code, expected_message", [ ({"name": "valid_name"}, 0, ""), - pytest.param({"name": "a" * (CHAT_ASSISTANT_LIMIT + 1)}, 102, "", marks=pytest.mark.skip(reason="issues/")), + pytest.param({"name": "a" * (CHAT_ASSISTANT_NAME_LIMIT + 1)}, 102, "", marks=pytest.mark.skip(reason="issues/")), pytest.param({"name": 1}, 100, "", marks=pytest.mark.skip(reason="issues/")), ({"name": ""}, 102, "`name` is required."), ({"name": "duplicated_name"}, 102, "Duplicated chat name in creating chat."), diff --git a/sdk/python/test/test_http_api/test_chat_assistant_management/test_delete_chat_assistants.py b/sdk/python/test/test_http_api/test_chat_assistant_management/test_delete_chat_assistants.py index efdbd340a..b9d8ae610 100644 --- a/sdk/python/test/test_http_api/test_chat_assistant_management/test_delete_chat_assistants.py +++ b/sdk/python/test/test_http_api/test_chat_assistant_management/test_delete_chat_assistants.py @@ -52,7 +52,7 @@ class TestChatAssistantsDelete: ], ) def test_basic_scenarios(self, get_http_api_auth, add_chat_assistants_func, payload, expected_code, expected_message, remaining): - _, _, _, chat_assistant_ids = add_chat_assistants_func + _, _, chat_assistant_ids = add_chat_assistants_func if callable(payload): payload = payload(chat_assistant_ids) res = delete_chat_assistants(get_http_api_auth, payload) @@ -73,7 +73,7 @@ class TestChatAssistantsDelete: ], ) def test_delete_partial_invalid_id(self, get_http_api_auth, add_chat_assistants_func, payload): - _, _, _, chat_assistant_ids = add_chat_assistants_func + _, _, chat_assistant_ids = add_chat_assistants_func if callable(payload): payload = payload(chat_assistant_ids) res = delete_chat_assistants(get_http_api_auth, payload) @@ -85,7 +85,7 @@ class TestChatAssistantsDelete: assert len(res["data"]) == 0 def test_repeated_deletion(self, get_http_api_auth, add_chat_assistants_func): - _, _, _, chat_assistant_ids = add_chat_assistants_func + _, _, chat_assistant_ids = add_chat_assistants_func res = delete_chat_assistants(get_http_api_auth, {"ids": chat_assistant_ids}) assert res["code"] == 0 @@ -95,7 +95,7 @@ class TestChatAssistantsDelete: @pytest.mark.skip(reason="issues/6876") def test_duplicate_deletion(self, get_http_api_auth, add_chat_assistants_func): - _, _, _, chat_assistant_ids = add_chat_assistants_func + _, _, chat_assistant_ids = add_chat_assistants_func res = delete_chat_assistants(get_http_api_auth, {"ids": chat_assistant_ids + chat_assistant_ids}) print(res) assert res["code"] == 0 @@ -105,6 +105,7 @@ class TestChatAssistantsDelete: res = delete_chat_assistants(get_http_api_auth) assert len(res["data"]) == 0 + @pytest.mark.slow def test_concurrent_deletion(self, get_http_api_auth): ids = batch_create_chat_assistants(get_http_api_auth, 100) diff --git a/sdk/python/test/test_http_api/test_chat_assistant_management/test_list_chat_assistants.py b/sdk/python/test/test_http_api/test_chat_assistant_management/test_list_chat_assistants.py index 7b663db1f..6c2f037e1 100644 --- a/sdk/python/test/test_http_api/test_chat_assistant_management/test_list_chat_assistants.py +++ b/sdk/python/test/test_http_api/test_chat_assistant_management/test_list_chat_assistants.py @@ -288,7 +288,7 @@ class TestChatAssistantsList: expected_num, expected_message, ): - _, _, _, chat_assistant_ids = add_chat_assistants + _, _, chat_assistant_ids = add_chat_assistants if callable(chat_assistant_id): params = {"id": chat_assistant_id(chat_assistant_ids)} else: @@ -323,7 +323,7 @@ class TestChatAssistantsList: expected_num, expected_message, ): - _, _, _, chat_assistant_ids = add_chat_assistants + _, _, chat_assistant_ids = add_chat_assistants if callable(chat_assistant_id): params = {"id": chat_assistant_id(chat_assistant_ids), "name": name} else: @@ -336,6 +336,7 @@ class TestChatAssistantsList: else: assert res["message"] == expected_message + @pytest.mark.slow def test_concurrent_list(self, get_http_api_auth): with ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(list_chat_assistants, get_http_api_auth) for i in range(100)] @@ -349,7 +350,7 @@ class TestChatAssistantsList: assert len(res["data"]) == 5 def test_list_chats_after_deleting_associated_dataset(self, get_http_api_auth, add_chat_assistants): - dataset_id, _, _, _ = add_chat_assistants + dataset_id, _, _ = add_chat_assistants res = delete_datasets(get_http_api_auth, {"ids": [dataset_id]}) assert res["code"] == 0 diff --git a/sdk/python/test/test_http_api/test_chat_assistant_management/test_update_chat_assistant.py b/sdk/python/test/test_http_api/test_chat_assistant_management/test_update_chat_assistant.py index e2bed4ed1..1f965bf05 100644 --- a/sdk/python/test/test_http_api/test_chat_assistant_management/test_update_chat_assistant.py +++ b/sdk/python/test/test_http_api/test_chat_assistant_management/test_update_chat_assistant.py @@ -14,7 +14,7 @@ # limitations under the License. # import pytest -from common import CHAT_ASSISTANT_LIMIT, INVALID_API_TOKEN, list_chat_assistants, update_chat_assistant +from common import CHAT_ASSISTANT_NAME_LIMIT, INVALID_API_TOKEN, list_chat_assistants, update_chat_assistant from libs.auth import RAGFlowHttpApiAuth from libs.utils import encode_avatar from libs.utils.file_utils import create_image_file @@ -44,7 +44,7 @@ class TestChatAssistantUpdate: "payload, expected_code, expected_message", [ ({"name": "valid_name"}, 0, ""), - pytest.param({"name": "a" * (CHAT_ASSISTANT_LIMIT + 1)}, 102, "", marks=pytest.mark.skip(reason="issues/")), + pytest.param({"name": "a" * (CHAT_ASSISTANT_NAME_LIMIT + 1)}, 102, "", marks=pytest.mark.skip(reason="issues/")), pytest.param({"name": 1}, 100, "", marks=pytest.mark.skip(reason="issues/")), ({"name": ""}, 102, "`name` cannot be empty."), ({"name": "test_chat_assistant_1"}, 102, "Duplicated chat name in updating chat."), @@ -52,7 +52,7 @@ class TestChatAssistantUpdate: ], ) def test_name(self, get_http_api_auth, add_chat_assistants_func, payload, expected_code, expected_message): - _, _, _, chat_assistant_ids = add_chat_assistants_func + _, _, chat_assistant_ids = add_chat_assistants_func res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) assert res["code"] == expected_code, res @@ -72,7 +72,7 @@ class TestChatAssistantUpdate: ], ) def test_dataset_ids(self, get_http_api_auth, add_chat_assistants_func, dataset_ids, expected_code, expected_message): - dataset_id, _, _, chat_assistant_ids = add_chat_assistants_func + dataset_id, _, chat_assistant_ids = add_chat_assistants_func payload = {"name": "ragflow test"} if callable(dataset_ids): payload["dataset_ids"] = dataset_ids(dataset_id) @@ -88,7 +88,7 @@ class TestChatAssistantUpdate: assert res["message"] == expected_message def test_avatar(self, get_http_api_auth, add_chat_assistants_func, tmp_path): - dataset_id, _, _, chat_assistant_ids = add_chat_assistants_func + dataset_id, _, chat_assistant_ids = add_chat_assistants_func fn = create_image_file(tmp_path / "ragflow_test.png") payload = {"name": "avatar_test", "avatar": encode_avatar(fn), "dataset_ids": [dataset_id]} res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) @@ -129,7 +129,7 @@ class TestChatAssistantUpdate: ], ) def test_llm(self, get_http_api_auth, add_chat_assistants_func, llm, expected_code, expected_message): - dataset_id, _, _, chat_assistant_ids = add_chat_assistants_func + dataset_id, _, chat_assistant_ids = add_chat_assistants_func payload = {"name": "llm_test", "dataset_ids": [dataset_id], "llm": llm} res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) assert res["code"] == expected_code @@ -196,7 +196,7 @@ class TestChatAssistantUpdate: ], ) def test_prompt(self, get_http_api_auth, add_chat_assistants_func, prompt, expected_code, expected_message): - dataset_id, _, _, chat_assistant_ids = add_chat_assistants_func + dataset_id, _, chat_assistant_ids = add_chat_assistants_func payload = {"name": "prompt_test", "dataset_ids": [dataset_id], "prompt": prompt} res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) assert res["code"] == expected_code diff --git a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_add_chunk.py b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_add_chunk.py index 0386b3fcd..77543355c 100644 --- a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_add_chunk.py +++ b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_add_chunk.py @@ -214,6 +214,7 @@ class TestAddChunk: assert res["code"] == 102 assert res["message"] == f"You don't own the document {document_id}." + @pytest.mark.slow @pytest.mark.skip(reason="issues/6411") def test_concurrent_add_chunk(self, get_http_api_auth, add_document): chunk_num = 50 diff --git a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_retrieval_chunks.py b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_retrieval_chunks.py index fd10443e6..9fb396fd8 100644 --- a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_retrieval_chunks.py +++ b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_retrieval_chunks.py @@ -291,6 +291,7 @@ class TestChunksRetrieval: assert res["code"] == 0 assert len(res["data"]["chunks"]) == 4 + @pytest.mark.slow def test_concurrent_retrieval(self, get_http_api_auth, add_chunks): from concurrent.futures import ThreadPoolExecutor diff --git a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_update_chunk.py b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_update_chunk.py index eab066135..78dfd665a 100644 --- a/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_update_chunk.py +++ b/sdk/python/test/test_http_api/test_chunk_management_within_dataset/test_update_chunk.py @@ -206,6 +206,7 @@ class TestUpdatedChunk: if expected_code != 0: assert res["message"] == expected_message + @pytest.mark.slow @pytest.mark.skipif(os.getenv("DOC_ENGINE") == "infinity", reason="issues/6554") def test_concurrent_update_chunk(self, get_http_api_auth, add_chunks): chunk_num = 50 diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_datasets.py b/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_datasets.py index 389a9a11b..90407e05a 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_datasets.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_datasets.py @@ -117,6 +117,7 @@ class TestDatasetsDeletion: res = list_datasets(get_http_api_auth) assert len(res["data"]) == 0 + @pytest.mark.slow def test_concurrent_deletion(self, get_http_api_auth): ids = batch_create_datasets(get_http_api_auth, 100) diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/test_list_datasets.py b/sdk/python/test/test_http_api/test_dataset_mangement/test_list_datasets.py index 0418919ff..48b9862b6 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/test_list_datasets.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/test_list_datasets.py @@ -337,6 +337,7 @@ class TestDatasetsList: else: assert res["message"] == expected_message + @pytest.mark.slow def test_concurrent_list(self, get_http_api_auth): with ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(list_datasets, get_http_api_auth) for i in range(100)] diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/test_update_dataset.py b/sdk/python/test/test_http_api/test_dataset_mangement/test_update_dataset.py index f189855dd..1213c5450 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/test_update_dataset.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/test_update_dataset.py @@ -236,6 +236,7 @@ class TestDatasetUpdate: res = update_dataset(get_http_api_auth, dataset_id, {"unknown_field": 0}) assert res["code"] == 100 + @pytest.mark.slow def test_concurrent_update(self, get_http_api_auth, add_dataset_func): dataset_id = add_dataset_func diff --git a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_delete_documents.py b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_delete_documents.py index 60aaa7ae9..bfe4515f6 100644 --- a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_delete_documents.py +++ b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_delete_documents.py @@ -140,6 +140,7 @@ class TestDocumentsDeletion: assert res["data"]["total"] == 0 +@pytest.mark.slow def test_concurrent_deletion(get_http_api_auth, add_dataset, tmp_path): documnets_num = 100 dataset_id = add_dataset diff --git a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_download_document.py b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_download_document.py index 0b11218e0..ab1264881 100644 --- a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_download_document.py +++ b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_download_document.py @@ -147,6 +147,7 @@ class TestDocumentDownload: ) +@pytest.mark.slow def test_concurrent_download(get_http_api_auth, add_dataset, tmp_path): document_count = 20 dataset_id = add_dataset diff --git a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_list_documents.py b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_list_documents.py index 15111ece9..2fa2cc849 100644 --- a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_list_documents.py +++ b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_list_documents.py @@ -406,6 +406,7 @@ class TestDocumentsList: else: assert res["message"] == expected_message + @pytest.mark.slow def test_concurrent_list(self, get_http_api_auth, add_documents): dataset_id, _ = add_documents diff --git a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_upload_documents.py b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_upload_documents.py index bf8576f4d..03957b1f7 100644 --- a/sdk/python/test/test_http_api/test_file_management_within_dataset/test_upload_documents.py +++ b/sdk/python/test/test_http_api/test_file_management_within_dataset/test_upload_documents.py @@ -186,6 +186,7 @@ class TestDocumentsUpload: res = list_datasets(get_http_api_auth, {"id": dataset_id}) assert res["data"][0]["document_count"] == expected_document_count + @pytest.mark.slow def test_concurrent_upload(self, get_http_api_auth, add_dataset_func, tmp_path): dataset_id = add_dataset_func diff --git a/sdk/python/test/test_http_api/test_session_management/test_create_session_with_chat_assistant.py b/sdk/python/test/test_http_api/test_session_management/test_create_session_with_chat_assistant.py new file mode 100644 index 000000000..eb2dbf638 --- /dev/null +++ b/sdk/python/test/test_http_api/test_session_management/test_create_session_with_chat_assistant.py @@ -0,0 +1,114 @@ +# +# Copyright 2025 The InfiniFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from concurrent.futures import ThreadPoolExecutor + +import pytest +from common import INVALID_API_TOKEN, SESSION_WITH_CHAT_NAME_LIMIT, create_session_with_chat_assistant, delete_chat_assistants, list_session_with_chat_assistants +from libs.auth import RAGFlowHttpApiAuth + + +class TestAuthorization: + @pytest.mark.parametrize( + "auth, expected_code, expected_message", + [ + (None, 0, "`Authorization` can't be empty"), + ( + RAGFlowHttpApiAuth(INVALID_API_TOKEN), + 109, + "Authentication error: API key is invalid!", + ), + ], + ) + def test_invalid_auth(self, auth, expected_code, expected_message): + res = create_session_with_chat_assistant(auth, "chat_assistant_id") + assert res["code"] == expected_code + assert res["message"] == expected_message + + +@pytest.mark.usefixtures("clear_session_with_chat_assistants") +class TestSessionWithChatAssistantCreate: + @pytest.mark.parametrize( + "payload, expected_code, expected_message", + [ + ({"name": "valid_name"}, 0, ""), + pytest.param({"name": "a" * (SESSION_WITH_CHAT_NAME_LIMIT + 1)}, 102, "", marks=pytest.mark.skip(reason="issues/")), + pytest.param({"name": 1}, 100, "", marks=pytest.mark.skip(reason="issues/")), + ({"name": ""}, 102, "`name` can not be empty."), + ({"name": "duplicated_name"}, 0, ""), + ({"name": "case insensitive"}, 0, ""), + ], + ) + def test_name(self, get_http_api_auth, add_chat_assistants, payload, expected_code, expected_message): + _, _, chat_assistant_ids = add_chat_assistants + if payload["name"] == "duplicated_name": + create_session_with_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) + elif payload["name"] == "case insensitive": + create_session_with_chat_assistant(get_http_api_auth, chat_assistant_ids[0], {"name": payload["name"].upper()}) + + res = create_session_with_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) + assert res["code"] == expected_code, res + if expected_code == 0: + assert res["data"]["name"] == payload["name"] + assert res["data"]["chat_id"] == chat_assistant_ids[0] + else: + assert res["message"] == expected_message + + @pytest.mark.parametrize( + "chat_assistant_id, expected_code, expected_message", + [ + ("", 100, ""), + ("invalid_chat_assistant_id", 102, "You do not own the assistant."), + ], + ) + def test_invalid_chat_assistant_id(self, get_http_api_auth, chat_assistant_id, expected_code, expected_message): + res = create_session_with_chat_assistant(get_http_api_auth, chat_assistant_id, {"name": "valid_name"}) + assert res["code"] == expected_code + assert res["message"] == expected_message + + @pytest.mark.slow + def test_concurrent_create_session(self, get_http_api_auth, add_chat_assistants): + chunk_num = 1000 + _, _, chat_assistant_ids = add_chat_assistants + res = list_session_with_chat_assistants(get_http_api_auth, chat_assistant_ids[0]) + if res["code"] != 0: + assert False, res + chunks_count = len(res["data"]) + + with ThreadPoolExecutor(max_workers=5) as executor: + futures = [ + executor.submit( + create_session_with_chat_assistant, + get_http_api_auth, + chat_assistant_ids[0], + {"name": f"session with chat assistant test {i}"}, + ) + for i in range(chunk_num) + ] + responses = [f.result() for f in futures] + assert all(r["code"] == 0 for r in responses) + res = list_session_with_chat_assistants(get_http_api_auth, chat_assistant_ids[0], {"page_size": chunk_num}) + if res["code"] != 0: + assert False, res + assert len(res["data"]) == chunks_count + chunk_num + + def test_add_session_to_deleted_chat_assistant(self, get_http_api_auth, add_chat_assistants): + _, _, chat_assistant_ids = add_chat_assistants + res = delete_chat_assistants(get_http_api_auth, {"ids": [chat_assistant_ids[0]]}) + assert res["code"] == 0 + res = create_session_with_chat_assistant(get_http_api_auth, chat_assistant_ids[0], {"name": "valid_name"}) + print(res) + assert res["code"] == 102 + assert res["message"] == "You do not own the assistant."