diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index d8a5cb84c..5223a6c08 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -22,4 +22,5 @@ test = [ [tool.pytest.ini_options] markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", + "wip: marks tests as work in progress (deselect with '-m \"not wip\"')" ] \ No newline at end of file diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/common.py b/sdk/python/test/test_http_api/test_dataset_mangement/common.py index f0062262b..049cb537e 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/common.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/common.py @@ -15,10 +15,11 @@ # import os + import requests -HOST_ADDRESS = os.getenv('HOST_ADDRESS', 'http://127.0.0.1:9380') -API_URL = f'{HOST_ADDRESS}/api/v1/datasets' +HOST_ADDRESS = os.getenv("HOST_ADDRESS", "http://127.0.0.1:9380") +API_URL = f"{HOST_ADDRESS}/api/v1/datasets" HEADERS = {"Content-Type": "application/json"} @@ -31,17 +32,26 @@ def create_dataset(auth, payload): return res.json() -def list_dataset(auth, params): +def list_dataset(auth, params=None): res = requests.get(url=API_URL, headers=HEADERS, auth=auth, params=params) return res.json() def update_dataset(auth, dataset_id, payload): - res = requests.put(url=f"{API_URL}/{dataset_id}", - headers=HEADERS, auth=auth, json=payload) + res = requests.put( + url=f"{API_URL}/{dataset_id}", headers=HEADERS, auth=auth, json=payload + ) return res.json() def delete_dataset(auth, payload=None): res = requests.delete(url=API_URL, headers=HEADERS, auth=auth, json=payload) return res.json() + + +def create_datasets(auth, num): + ids = [] + for i in range(num): + res = create_dataset(auth, {"name": f"dataset_{i}"}) + ids.append(res["data"]["id"]) + return ids diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/conftest.py b/sdk/python/test/test_http_api/test_dataset_mangement/conftest.py index fec1aee99..8f7013fa4 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/conftest.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/conftest.py @@ -15,7 +15,6 @@ # import pytest - from common import delete_dataset diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/test_create_dataset.py b/sdk/python/test/test_http_api/test_dataset_mangement/test_create_dataset.py index cb21cb06d..5bb954063 100644 --- a/sdk/python/test/test_http_api/test_dataset_mangement/test_create_dataset.py +++ b/sdk/python/test/test_http_api/test_dataset_mangement/test_create_dataset.py @@ -13,39 +13,49 @@ # See the License for the specific language governing permissions and # limitations under the License. # -import pytest import base64 - from pathlib import Path -from common import create_dataset, INVALID_API_TOKEN, DATASET_NAME_LIMIT +import pytest +from common import DATASET_NAME_LIMIT, INVALID_API_TOKEN, create_dataset from libs.auth import RAGFlowHttpApiAuth class TestAuthorization: - def test_invalid_auth(self): - INVALID_API_KEY = RAGFlowHttpApiAuth(INVALID_API_TOKEN) - res = create_dataset(INVALID_API_KEY, {"name": "auth_test"}) - - assert res["code"] == 109 - assert res["message"] == 'Authentication error: API key is invalid!' + @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_dataset(auth, {"name": "auth_test"}) + assert res["code"] == expected_code + assert res["message"] == expected_message class TestDatasetCreation: - @pytest.mark.parametrize("payload, expected_code", [ - ({"name": "valid_name"}, 0), - ({"name": "a"*(DATASET_NAME_LIMIT+1)}, 102), - ({"name": 0}, 100), - ({"name": ""}, 102), - ({"name": "duplicated_name"}, 102), - ({"name": "case_insensitive"}, 102), - ]) + @pytest.mark.parametrize( + "payload, expected_code", + [ + ({"name": "valid_name"}, 0), + ({"name": "a" * (DATASET_NAME_LIMIT + 1)}, 102), + ({"name": 0}, 100), + ({"name": ""}, 102), + ({"name": "duplicated_name"}, 102), + ({"name": "case_insensitive"}, 102), + ], + ) def test_basic_scenarios(self, get_http_api_auth, payload, expected_code): if payload["name"] == "duplicated_name": create_dataset(get_http_api_auth, payload) elif payload["name"] == "case_insensitive": - create_dataset(get_http_api_auth, { - "name": payload["name"].upper()}) + create_dataset(get_http_api_auth, {"name": payload["name"].upper()}) res = create_dataset(get_http_api_auth, payload) @@ -58,7 +68,7 @@ class TestDatasetCreation: @pytest.mark.slow def test_dataset_10k(self, get_http_api_auth): - for i in range(10000): + for i in range(10_000): payload = {"name": f"dataset_{i}"} res = create_dataset(get_http_api_auth, payload) assert res["code"] == 0, f"Failed to create dataset {i}" @@ -74,33 +84,33 @@ class TestAdvancedConfigurations: payload = { "name": "avatar_test", - "avatar": encode_avatar(Path(request.config.rootdir) / 'test/data/logo.svg') + "avatar": encode_avatar( + Path(request.config.rootdir) / "test/data/logo.svg" + ), } res = create_dataset(get_http_api_auth, payload) assert res["code"] == 0 def test_description(self, get_http_api_auth): - payload = { - "name": "description_test", - "description": "a" * 65536 - } + payload = {"name": "description_test", "description": "a" * 65536} res = create_dataset(get_http_api_auth, payload) assert res["code"] == 0 - @pytest.mark.parametrize("name, permission, expected_code", [ - ("me", "me", 0), - ("team", "team", 0), - pytest.param("empty_permission", "", 0, - marks=pytest.mark.xfail(reason='issue#5709')), - ("me_upercase", "ME", 102), - ("team_upercase", "TEAM", 102), - ("other_permission", "other_permission", 102) - ]) + @pytest.mark.parametrize( + "name, permission, expected_code", + [ + ("me", "me", 0), + ("team", "team", 0), + pytest.param( + "empty_permission", "", 0, marks=pytest.mark.xfail(reason="issue#5709") + ), + ("me_upercase", "ME", 102), + ("team_upercase", "TEAM", 102), + ("other_permission", "other_permission", 102), + ], + ) def test_permission(self, get_http_api_auth, name, permission, expected_code): - payload = { - "name": name, - "permission": permission - } + payload = {"name": name, "permission": permission} res = create_dataset(get_http_api_auth, payload) assert res["code"] == expected_code if expected_code == 0 and permission != "": @@ -108,29 +118,33 @@ class TestAdvancedConfigurations: if permission == "": assert res["data"]["permission"] == "me" - @pytest.mark.parametrize("name, chunk_method, expected_code", [ - ("naive", "naive", 0), - ("manual", "manual", 0), - ("qa", "qa", 0), - ("table", "table", 0), - ("paper", "paper", 0), - ("book", "book", 0), - ("laws", "laws", 0), - ("presentation", "presentation", 0), - ("picture", "picture", 0), - ("one", "one", 0), - ("picknowledge_graphture", "knowledge_graph", 0), - ("email", "email", 0), - ("tag", "tag", 0), - pytest.param("empty_chunk_method", "", 0, - marks=pytest.mark.xfail(reason='issue#5709')), - ("other_chunk_method", "other_chunk_method", 102) - ]) + @pytest.mark.parametrize( + "name, chunk_method, expected_code", + [ + ("naive", "naive", 0), + ("manual", "manual", 0), + ("qa", "qa", 0), + ("table", "table", 0), + ("paper", "paper", 0), + ("book", "book", 0), + ("laws", "laws", 0), + ("presentation", "presentation", 0), + ("picture", "picture", 0), + ("one", "one", 0), + ("picknowledge_graphture", "knowledge_graph", 0), + ("email", "email", 0), + ("tag", "tag", 0), + pytest.param( + "empty_chunk_method", + "", + 0, + marks=pytest.mark.xfail(reason="issue#5709"), + ), + ("other_chunk_method", "other_chunk_method", 102), + ], + ) def test_chunk_method(self, get_http_api_auth, name, chunk_method, expected_code): - payload = { - "name": name, - "chunk_method": chunk_method - } + payload = {"name": name, "chunk_method": chunk_method} res = create_dataset(get_http_api_auth, payload) assert res["code"] == expected_code if expected_code == 0 and chunk_method != "": @@ -138,105 +152,172 @@ class TestAdvancedConfigurations: if chunk_method == "": assert res["data"]["chunk_method"] == "naive" - @pytest.mark.parametrize("name, embedding_model, expected_code", [ - ("BAAI/bge-large-zh-v1.5", - "BAAI/bge-large-zh-v1.5", 0), - ("BAAI/bge-base-en-v1.5", - "BAAI/bge-base-en-v1.5", 0), - ("BAAI/bge-large-en-v1.5", - "BAAI/bge-large-en-v1.5", 0), - ("BAAI/bge-small-en-v1.5", - "BAAI/bge-small-en-v1.5", 0), - ("BAAI/bge-small-zh-v1.5", - "BAAI/bge-small-zh-v1.5", 0), - ("jinaai/jina-embeddings-v2-base-en", - "jinaai/jina-embeddings-v2-base-en", 0), - ("jinaai/jina-embeddings-v2-small-en", - "jinaai/jina-embeddings-v2-small-en", 0), - ("nomic-ai/nomic-embed-text-v1.5", - "nomic-ai/nomic-embed-text-v1.5", 0), - ("sentence-transformers/all-MiniLM-L6-v2", - "sentence-transformers/all-MiniLM-L6-v2", 0), - ("text-embedding-v2", - "text-embedding-v2", 0), - ("text-embedding-v3", - "text-embedding-v3", 0), - ("maidalun1020/bce-embedding-base_v1", - "maidalun1020/bce-embedding-base_v1", 0), - ("other_embedding_model", - "other_embedding_model", 102) - ]) - def test_embedding_model(self, get_http_api_auth, name, embedding_model, expected_code): - payload = { - "name": name, - "embedding_model": embedding_model - } + @pytest.mark.parametrize( + "name, embedding_model, expected_code", + [ + ("BAAI/bge-large-zh-v1.5", "BAAI/bge-large-zh-v1.5", 0), + ("BAAI/bge-base-en-v1.5", "BAAI/bge-base-en-v1.5", 0), + ("BAAI/bge-large-en-v1.5", "BAAI/bge-large-en-v1.5", 0), + ("BAAI/bge-small-en-v1.5", "BAAI/bge-small-en-v1.5", 0), + ("BAAI/bge-small-zh-v1.5", "BAAI/bge-small-zh-v1.5", 0), + ( + "jinaai/jina-embeddings-v2-base-en", + "jinaai/jina-embeddings-v2-base-en", + 0, + ), + ( + "jinaai/jina-embeddings-v2-small-en", + "jinaai/jina-embeddings-v2-small-en", + 0, + ), + ("nomic-ai/nomic-embed-text-v1.5", "nomic-ai/nomic-embed-text-v1.5", 0), + ( + "sentence-transformers/all-MiniLM-L6-v2", + "sentence-transformers/all-MiniLM-L6-v2", + 0, + ), + ("text-embedding-v2", "text-embedding-v2", 0), + ("text-embedding-v3", "text-embedding-v3", 0), + ( + "maidalun1020/bce-embedding-base_v1", + "maidalun1020/bce-embedding-base_v1", + 0, + ), + ("other_embedding_model", "other_embedding_model", 102), + ], + ) + def test_embedding_model( + self, get_http_api_auth, name, embedding_model, expected_code + ): + payload = {"name": name, "embedding_model": embedding_model} res = create_dataset(get_http_api_auth, payload) assert res["code"] == expected_code if expected_code == 0: assert res["data"]["embedding_model"] == embedding_model - @pytest.mark.parametrize("name, chunk_method, parser_config, expected_code", [ - ("naive_default", "naive", - {"chunk_token_num": 128, - "layout_recognize": "DeepDOC", - "html4excel": False, - "delimiter": "\n!?。;!?", - "task_page_size": 12, - "raptor": {"use_raptor": False} - }, - 0), - ("naive_empty", "naive", {}, 0), - pytest.param("naive_chunk_token_num_negative", "naive", - {"chunk_token_num": -1}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_chunk_token_num_zero", "naive", - {"chunk_token_num": 0}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_chunk_token_num_float", "naive", - {"chunk_token_num": 3.14}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_chunk_token_num_max", "naive", - {"chunk_token_num": 1024*1024*1024}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_chunk_token_num_str", "naive", - {"chunk_token_num": '1024'}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - ("naive_layout_recognize_DeepDOC", "naive", - {"layout_recognize": "DeepDOC"}, 0), - ("naive_layout_recognize_Naive", "naive", - {"layout_recognize": "Naive"}, 0), - ("naive_html4excel_true", "naive", {"html4excel": True}, 0), - ("naive_html4excel_false", "naive", {"html4excel": False}, 0), - pytest.param("naive_html4excel_not_bool", "naive", { - "html4excel": 1}, 102, marks=pytest.mark.xfail(reason='issue#5719')), - ("naive_delimiter_empty", "naive", {"delimiter": ""}, 0), - ("naive_delimiter_backticks", "naive", {"delimiter": "`##`"}, 0), - pytest.param("naive_delimiterl_not_str", "naive", { - "delimiterl": 1}, 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_task_page_size_negative", "naive", - {"task_page_size": -1}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_task_page_size_zero", "naive", - {"task_page_size": 0}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_task_page_size_float", "naive", - {"task_page_size": 3.14}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_task_page_size_max", "naive", - {"task_page_size": 1024*1024*1024}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - pytest.param("naive_task_page_size_str", "naive", - {"task_page_size": '1024'}, - 102, marks=pytest.mark.xfail(reason='issue#5719')), - ("naive_raptor_true", "naive", {"raptor": {"use_raptor": True}}, 0), - ("naive_raptor_false", "naive", {"raptor": {"use_raptor": False}}, 0), - ]) - def test_parser_configs(self, get_http_api_auth, name, chunk_method, parser_config, expected_code): + @pytest.mark.parametrize( + "name, chunk_method, parser_config, expected_code", + [ + ( + "naive_default", + "naive", + { + "chunk_token_num": 128, + "layout_recognize": "DeepDOC", + "html4excel": False, + "delimiter": "\n!?。;!?", + "task_page_size": 12, + "raptor": {"use_raptor": False}, + }, + 0, + ), + ("naive_empty", "naive", {}, 0), + pytest.param( + "naive_chunk_token_num_negative", + "naive", + {"chunk_token_num": -1}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_chunk_token_num_zero", + "naive", + {"chunk_token_num": 0}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_chunk_token_num_float", + "naive", + {"chunk_token_num": 3.14}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_chunk_token_num_max", + "naive", + {"chunk_token_num": 1024 * 1024 * 1024}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_chunk_token_num_str", + "naive", + {"chunk_token_num": "1024"}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + ( + "naive_layout_recognize_DeepDOC", + "naive", + {"layout_recognize": "DeepDOC"}, + 0, + ), + ("naive_layout_recognize_Naive", "naive", {"layout_recognize": "Naive"}, 0), + ("naive_html4excel_true", "naive", {"html4excel": True}, 0), + ("naive_html4excel_false", "naive", {"html4excel": False}, 0), + pytest.param( + "naive_html4excel_not_bool", + "naive", + {"html4excel": 1}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + ("naive_delimiter_empty", "naive", {"delimiter": ""}, 0), + ("naive_delimiter_backticks", "naive", {"delimiter": "`##`"}, 0), + pytest.param( + "naive_delimiterl_not_str", + "naive", + {"delimiterl": 1}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_task_page_size_negative", + "naive", + {"task_page_size": -1}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_task_page_size_zero", + "naive", + {"task_page_size": 0}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_task_page_size_float", + "naive", + {"task_page_size": 3.14}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_task_page_size_max", + "naive", + {"task_page_size": 1024 * 1024 * 1024}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + pytest.param( + "naive_task_page_size_str", + "naive", + {"task_page_size": "1024"}, + 102, + marks=pytest.mark.xfail(reason="issue#5719"), + ), + ("naive_raptor_true", "naive", {"raptor": {"use_raptor": True}}, 0), + ("naive_raptor_false", "naive", {"raptor": {"use_raptor": False}}, 0), + ], + ) + def test_parser_configs( + self, get_http_api_auth, name, chunk_method, parser_config, expected_code + ): payload = { "name": name, "chunk_method": chunk_method, - "parser_config": parser_config + "parser_config": parser_config, } res = create_dataset(get_http_api_auth, payload) # print(res) @@ -245,8 +326,10 @@ class TestAdvancedConfigurations: for k, v in parser_config.items(): assert res["data"]["parser_config"][k] == v if parser_config == {}: - assert res["data"]["parser_config"] == {"chunk_token_num": 128, - "delimiter": "\\n!?;。;!?", - "html4excel": False, - "layout_recognize": "DeepDOC", - "raptor": {"use_raptor": False}} + assert res["data"]["parser_config"] == { + "chunk_token_num": 128, + "delimiter": "\\n!?;。;!?", + "html4excel": False, + "layout_recognize": "DeepDOC", + "raptor": {"use_raptor": False}, + } diff --git a/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_dataset.py b/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_dataset.py new file mode 100644 index 000000000..9192f4fd1 --- /dev/null +++ b/sdk/python/test/test_http_api/test_dataset_mangement/test_delete_dataset.py @@ -0,0 +1,167 @@ +# +# 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, + create_datasets, + delete_dataset, + list_dataset, +) +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, get_http_api_auth, auth, expected_code, expected_message + ): + ids = create_datasets(get_http_api_auth, 1) + res = delete_dataset(auth, {"ids": ids}) + assert res["code"] == expected_code + assert res["message"] == expected_message + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 1 + + +class TestDatasetDeletion: + @pytest.mark.parametrize( + "payload, expected_code, expected_message, remaining", + [ + (None, 0, "", 0), + ({"ids": []}, 0, "", 0), + ({"ids": ["invalid_id"]}, 102, "You don't own the dataset invalid_id", 3), + ( + {"ids": ["\n!?。;!?\"'"]}, + 102, + "You don't own the dataset \n!?。;!?\"'", + 3, + ), + ( + "not json", + 100, + "AttributeError(\"'str' object has no attribute 'get'\")", + 3, + ), + ], + ) + def test_basic_scenarios( + self, get_http_api_auth, payload, expected_code, expected_message, remaining + ): + create_datasets(get_http_api_auth, 3) + res = delete_dataset(get_http_api_auth, payload) + assert res["code"] == expected_code + if res["code"] != 0: + assert res["message"] == expected_message + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == remaining + + def test_delete_one(self, get_http_api_auth): + count = 3 + ids = create_datasets(get_http_api_auth, count) + res = delete_dataset(get_http_api_auth, {"ids": ids[:1]}) + assert res["code"] == 0 + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == count - 1 + + def test_delete_multi(self, get_http_api_auth): + ids = create_datasets(get_http_api_auth, 3) + res = delete_dataset(get_http_api_auth, {"ids": ids}) + assert res["code"] == 0 + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 0 + + @pytest.mark.xfail(reason="issue#5760") + def test_delete_partial_invalid_id_at_beginning(self, get_http_api_auth): + count = 3 + ids = create_datasets(get_http_api_auth, count) + res = delete_dataset(get_http_api_auth, {"ids": ["invalid_id"] + ids}) + assert res["code"] == 102 + assert res["message"] == "You don't own the dataset invalid_id" + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 3 + + @pytest.mark.xfail(reason="issue#5760") + def test_delete_partial_invalid_id_in_middle(self, get_http_api_auth): + count = 3 + ids = create_datasets(get_http_api_auth, count) + res = delete_dataset( + get_http_api_auth, {"ids": ids[:1] + ["invalid_id"] + ids[1:3]} + ) + assert res["code"] == 102 + assert res["message"] == "You don't own the dataset invalid_id" + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 3 + + @pytest.mark.xfail(reason="issue#5760") + def test_delete_partial_invalid_id_at_end(self, get_http_api_auth): + count = 3 + ids = create_datasets(get_http_api_auth, count) + res = delete_dataset(get_http_api_auth, {"ids": ids + ["invalid_id"]}) + assert res["code"] == 102 + assert res["message"] == "You don't own the dataset invalid_id" + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 3 + + def test_repeated_deletion(self, get_http_api_auth): + ids = create_datasets(get_http_api_auth, 1) + res = delete_dataset(get_http_api_auth, {"ids": ids}) + assert res["code"] == 0 + + res = delete_dataset(get_http_api_auth, {"ids": ids}) + assert res["code"] == 102 + assert res["message"] == f"You don't own the dataset {ids[0]}" + + def test_concurrent_deletion(self, get_http_api_auth): + ids = create_datasets(get_http_api_auth, 100) + + with ThreadPoolExecutor(max_workers=5) as executor: + futures = [ + executor.submit( + delete_dataset, get_http_api_auth, {"ids": ids[i : i + 1]} + ) + for i in range(100) + ] + responses = [f.result() for f in futures] + assert all(r["code"] == 0 for r in responses) + + @pytest.mark.slow + def test_delete_10k(self, get_http_api_auth): + ids = create_datasets(get_http_api_auth, 10_000) + res = delete_dataset(get_http_api_auth, {"ids": ids}) + assert res["code"] == 0 + + res = list_dataset(get_http_api_auth) + assert len(res["data"]) == 0