Test: Added test cases for Create Session With Chat Assistant HTTP API (#6902)

### 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 cases
This commit is contained in:
liu an 2025-04-09 17:21:48 +08:00 committed by GitHub
parent 9d9f2dacd2
commit ae107f31d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 237 additions and 42 deletions

View File

@ -28,11 +28,14 @@ FILE_API_URL = "/api/v1/datasets/{dataset_id}/documents"
FILE_CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/chunks" FILE_CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/chunks"
CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/documents/{document_id}/chunks" CHUNK_API_URL = "/api/v1/datasets/{dataset_id}/documents/{document_id}/chunks"
CHAT_ASSISTANT_API_URL = "/api/v1/chats" 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" INVALID_API_TOKEN = "invalid_key_123"
DATASET_NAME_LIMIT = 128 DATASET_NAME_LIMIT = 128
DOCUMENT_NAME_LIMIT = 128 DOCUMENT_NAME_LIMIT = 128
CHAT_ASSISTANT_LIMIT = 255 CHAT_ASSISTANT_NAME_LIMIT = 255
SESSION_WITH_CHAT_NAME_LIMIT = 255
# DATASET MANAGEMENT # 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": []}) res = create_chat_assistant(auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": []})
chat_assistant_ids.append(res["data"]["id"]) chat_assistant_ids.append(res["data"]["id"])
return chat_assistant_ids 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()

View File

@ -15,7 +15,17 @@
# #
import pytest 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 import wait_for
from libs.utils.file_utils import ( from libs.utils.file_utils import (
create_docx_file, create_docx_file,
@ -41,15 +51,30 @@ def condition(_auth, _dataset_id):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def clear_datasets(get_http_api_auth): def clear_datasets(request, get_http_api_auth):
yield def cleanup():
delete_datasets(get_http_api_auth) delete_datasets(get_http_api_auth)
request.addfinalizer(cleanup)
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def clear_chat_assistants(get_http_api_auth): def clear_chat_assistants(request, get_http_api_auth):
yield def cleanup():
delete_chat_assistants(get_http_api_auth) 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 @pytest.fixture
@ -126,3 +151,22 @@ def add_chunks(get_http_api_auth, add_document):
sleep(1) sleep(1)
return dataset_id, document_id, chunk_ids 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

View File

@ -14,36 +14,33 @@
# limitations under the License. # limitations under the License.
# #
import pytest 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") @wait_for(30, 1, "Document parsing timeout")
def add_chat_assistants(request, get_http_api_auth, add_chunks): def condition(_auth, _dataset_id):
def cleanup(): res = list_documnets(_auth, _dataset_id)
delete_chat_assistants(get_http_api_auth) for doc in res["data"]["docs"]:
if doc["run"] != "DONE":
request.addfinalizer(cleanup) return False
return True
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
@pytest.fixture(scope="function") @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(): def cleanup():
delete_chat_assistants(get_http_api_auth) delete_chat_assistants(get_http_api_auth)
request.addfinalizer(cleanup) 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 = [] chat_assistant_ids = []
for i in range(5): for i in range(5):
res = create_chat_assistant(get_http_api_auth, {"name": f"test_chat_assistant_{i}", "dataset_ids": [dataset_id]}) 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"]) 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

View File

@ -15,7 +15,7 @@
# #
import pytest 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.auth import RAGFlowHttpApiAuth
from libs.utils import encode_avatar from libs.utils import encode_avatar
from libs.utils.file_utils import create_image_file from libs.utils.file_utils import create_image_file
@ -46,7 +46,7 @@ class TestChatAssistantCreate:
"payload, expected_code, expected_message", "payload, expected_code, expected_message",
[ [
({"name": "valid_name"}, 0, ""), ({"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/")), pytest.param({"name": 1}, 100, "", marks=pytest.mark.skip(reason="issues/")),
({"name": ""}, 102, "`name` is required."), ({"name": ""}, 102, "`name` is required."),
({"name": "duplicated_name"}, 102, "Duplicated chat name in creating chat."), ({"name": "duplicated_name"}, 102, "Duplicated chat name in creating chat."),

View File

@ -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): 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): if callable(payload):
payload = payload(chat_assistant_ids) payload = payload(chat_assistant_ids)
res = delete_chat_assistants(get_http_api_auth, payload) 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): 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): if callable(payload):
payload = payload(chat_assistant_ids) payload = payload(chat_assistant_ids)
res = delete_chat_assistants(get_http_api_auth, payload) res = delete_chat_assistants(get_http_api_auth, payload)
@ -85,7 +85,7 @@ class TestChatAssistantsDelete:
assert len(res["data"]) == 0 assert len(res["data"]) == 0
def test_repeated_deletion(self, get_http_api_auth, add_chat_assistants_func): 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}) res = delete_chat_assistants(get_http_api_auth, {"ids": chat_assistant_ids})
assert res["code"] == 0 assert res["code"] == 0
@ -95,7 +95,7 @@ class TestChatAssistantsDelete:
@pytest.mark.skip(reason="issues/6876") @pytest.mark.skip(reason="issues/6876")
def test_duplicate_deletion(self, get_http_api_auth, add_chat_assistants_func): 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}) res = delete_chat_assistants(get_http_api_auth, {"ids": chat_assistant_ids + chat_assistant_ids})
print(res) print(res)
assert res["code"] == 0 assert res["code"] == 0
@ -105,6 +105,7 @@ class TestChatAssistantsDelete:
res = delete_chat_assistants(get_http_api_auth) res = delete_chat_assistants(get_http_api_auth)
assert len(res["data"]) == 0 assert len(res["data"]) == 0
@pytest.mark.slow
def test_concurrent_deletion(self, get_http_api_auth): def test_concurrent_deletion(self, get_http_api_auth):
ids = batch_create_chat_assistants(get_http_api_auth, 100) ids = batch_create_chat_assistants(get_http_api_auth, 100)

View File

@ -288,7 +288,7 @@ class TestChatAssistantsList:
expected_num, expected_num,
expected_message, expected_message,
): ):
_, _, _, chat_assistant_ids = add_chat_assistants _, _, chat_assistant_ids = add_chat_assistants
if callable(chat_assistant_id): if callable(chat_assistant_id):
params = {"id": chat_assistant_id(chat_assistant_ids)} params = {"id": chat_assistant_id(chat_assistant_ids)}
else: else:
@ -323,7 +323,7 @@ class TestChatAssistantsList:
expected_num, expected_num,
expected_message, expected_message,
): ):
_, _, _, chat_assistant_ids = add_chat_assistants _, _, chat_assistant_ids = add_chat_assistants
if callable(chat_assistant_id): if callable(chat_assistant_id):
params = {"id": chat_assistant_id(chat_assistant_ids), "name": name} params = {"id": chat_assistant_id(chat_assistant_ids), "name": name}
else: else:
@ -336,6 +336,7 @@ class TestChatAssistantsList:
else: else:
assert res["message"] == expected_message assert res["message"] == expected_message
@pytest.mark.slow
def test_concurrent_list(self, get_http_api_auth): def test_concurrent_list(self, get_http_api_auth):
with ThreadPoolExecutor(max_workers=5) as executor: with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(list_chat_assistants, get_http_api_auth) for i in range(100)] 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 assert len(res["data"]) == 5
def test_list_chats_after_deleting_associated_dataset(self, get_http_api_auth, add_chat_assistants): 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]}) res = delete_datasets(get_http_api_auth, {"ids": [dataset_id]})
assert res["code"] == 0 assert res["code"] == 0

View File

@ -14,7 +14,7 @@
# limitations under the License. # limitations under the License.
# #
import pytest 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.auth import RAGFlowHttpApiAuth
from libs.utils import encode_avatar from libs.utils import encode_avatar
from libs.utils.file_utils import create_image_file from libs.utils.file_utils import create_image_file
@ -44,7 +44,7 @@ class TestChatAssistantUpdate:
"payload, expected_code, expected_message", "payload, expected_code, expected_message",
[ [
({"name": "valid_name"}, 0, ""), ({"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/")), pytest.param({"name": 1}, 100, "", marks=pytest.mark.skip(reason="issues/")),
({"name": ""}, 102, "`name` cannot be empty."), ({"name": ""}, 102, "`name` cannot be empty."),
({"name": "test_chat_assistant_1"}, 102, "Duplicated chat name in updating chat."), ({"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): 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) res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload)
assert res["code"] == expected_code, res 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): 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"} payload = {"name": "ragflow test"}
if callable(dataset_ids): if callable(dataset_ids):
payload["dataset_ids"] = dataset_ids(dataset_id) payload["dataset_ids"] = dataset_ids(dataset_id)
@ -88,7 +88,7 @@ class TestChatAssistantUpdate:
assert res["message"] == expected_message assert res["message"] == expected_message
def test_avatar(self, get_http_api_auth, add_chat_assistants_func, tmp_path): 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") fn = create_image_file(tmp_path / "ragflow_test.png")
payload = {"name": "avatar_test", "avatar": encode_avatar(fn), "dataset_ids": [dataset_id]} 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) 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): 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} payload = {"name": "llm_test", "dataset_ids": [dataset_id], "llm": llm}
res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload)
assert res["code"] == expected_code 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): 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} payload = {"name": "prompt_test", "dataset_ids": [dataset_id], "prompt": prompt}
res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload) res = update_chat_assistant(get_http_api_auth, chat_assistant_ids[0], payload)
assert res["code"] == expected_code assert res["code"] == expected_code

View File

@ -214,6 +214,7 @@ class TestAddChunk:
assert res["code"] == 102 assert res["code"] == 102
assert res["message"] == f"You don't own the document {document_id}." assert res["message"] == f"You don't own the document {document_id}."
@pytest.mark.slow
@pytest.mark.skip(reason="issues/6411") @pytest.mark.skip(reason="issues/6411")
def test_concurrent_add_chunk(self, get_http_api_auth, add_document): def test_concurrent_add_chunk(self, get_http_api_auth, add_document):
chunk_num = 50 chunk_num = 50

View File

@ -291,6 +291,7 @@ class TestChunksRetrieval:
assert res["code"] == 0 assert res["code"] == 0
assert len(res["data"]["chunks"]) == 4 assert len(res["data"]["chunks"]) == 4
@pytest.mark.slow
def test_concurrent_retrieval(self, get_http_api_auth, add_chunks): def test_concurrent_retrieval(self, get_http_api_auth, add_chunks):
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor

View File

@ -206,6 +206,7 @@ class TestUpdatedChunk:
if expected_code != 0: if expected_code != 0:
assert res["message"] == expected_message assert res["message"] == expected_message
@pytest.mark.slow
@pytest.mark.skipif(os.getenv("DOC_ENGINE") == "infinity", reason="issues/6554") @pytest.mark.skipif(os.getenv("DOC_ENGINE") == "infinity", reason="issues/6554")
def test_concurrent_update_chunk(self, get_http_api_auth, add_chunks): def test_concurrent_update_chunk(self, get_http_api_auth, add_chunks):
chunk_num = 50 chunk_num = 50

View File

@ -117,6 +117,7 @@ class TestDatasetsDeletion:
res = list_datasets(get_http_api_auth) res = list_datasets(get_http_api_auth)
assert len(res["data"]) == 0 assert len(res["data"]) == 0
@pytest.mark.slow
def test_concurrent_deletion(self, get_http_api_auth): def test_concurrent_deletion(self, get_http_api_auth):
ids = batch_create_datasets(get_http_api_auth, 100) ids = batch_create_datasets(get_http_api_auth, 100)

View File

@ -337,6 +337,7 @@ class TestDatasetsList:
else: else:
assert res["message"] == expected_message assert res["message"] == expected_message
@pytest.mark.slow
def test_concurrent_list(self, get_http_api_auth): def test_concurrent_list(self, get_http_api_auth):
with ThreadPoolExecutor(max_workers=5) as executor: with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(list_datasets, get_http_api_auth) for i in range(100)] futures = [executor.submit(list_datasets, get_http_api_auth) for i in range(100)]

View File

@ -236,6 +236,7 @@ class TestDatasetUpdate:
res = update_dataset(get_http_api_auth, dataset_id, {"unknown_field": 0}) res = update_dataset(get_http_api_auth, dataset_id, {"unknown_field": 0})
assert res["code"] == 100 assert res["code"] == 100
@pytest.mark.slow
def test_concurrent_update(self, get_http_api_auth, add_dataset_func): def test_concurrent_update(self, get_http_api_auth, add_dataset_func):
dataset_id = add_dataset_func dataset_id = add_dataset_func

View File

@ -140,6 +140,7 @@ class TestDocumentsDeletion:
assert res["data"]["total"] == 0 assert res["data"]["total"] == 0
@pytest.mark.slow
def test_concurrent_deletion(get_http_api_auth, add_dataset, tmp_path): def test_concurrent_deletion(get_http_api_auth, add_dataset, tmp_path):
documnets_num = 100 documnets_num = 100
dataset_id = add_dataset dataset_id = add_dataset

View File

@ -147,6 +147,7 @@ class TestDocumentDownload:
) )
@pytest.mark.slow
def test_concurrent_download(get_http_api_auth, add_dataset, tmp_path): def test_concurrent_download(get_http_api_auth, add_dataset, tmp_path):
document_count = 20 document_count = 20
dataset_id = add_dataset dataset_id = add_dataset

View File

@ -406,6 +406,7 @@ class TestDocumentsList:
else: else:
assert res["message"] == expected_message assert res["message"] == expected_message
@pytest.mark.slow
def test_concurrent_list(self, get_http_api_auth, add_documents): def test_concurrent_list(self, get_http_api_auth, add_documents):
dataset_id, _ = add_documents dataset_id, _ = add_documents

View File

@ -186,6 +186,7 @@ class TestDocumentsUpload:
res = list_datasets(get_http_api_auth, {"id": dataset_id}) res = list_datasets(get_http_api_auth, {"id": dataset_id})
assert res["data"][0]["document_count"] == expected_document_count 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): def test_concurrent_upload(self, get_http_api_auth, add_dataset_func, tmp_path):
dataset_id = add_dataset_func dataset_id = add_dataset_func

View File

@ -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."