### What problem does this PR solve? cover [create session with chat assistant](https://ragflow.io/docs/dev/http_api_reference#create-session-with-chat-assistant) endpoints ### Type of change - [x] add test casestags/v0.18.0
| @@ -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() | |||
| @@ -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(request, get_http_api_auth): | |||
| def cleanup(): | |||
| delete_chat_assistants(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_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 | |||
| @@ -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 | |||
| @@ -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."), | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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)] | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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, "<MethodNotAllowed '405: Method Not Allowed'>"), | |||
| ("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." | |||