Move test files (#10765)

### What problem does this PR solve?

Move some test files to test/testcases

### Type of change

- [x] Refactoring

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2025-10-23 22:31:55 +08:00
committed by GitHub
parent 0ff2042fc1
commit 92739ea804
7 changed files with 0 additions and 0 deletions

36
test/testcases/configs.py Normal file
View File

@ -0,0 +1,36 @@
#
# 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.
#
import os
import pytest
HOST_ADDRESS = os.getenv("HOST_ADDRESS", "http://127.0.0.1:9380")
VERSION = "v1"
ZHIPU_AI_API_KEY = os.getenv("ZHIPU_AI_API_KEY")
if ZHIPU_AI_API_KEY is None:
pytest.exit("Error: Environment variable ZHIPU_AI_API_KEY must be set")
EMAIL = "qa@infiniflow.org"
# password is "123"
PASSWORD = """ctAseGvejiaSWWZ88T/m4FQVOpQyUvP+x7sXtdv3feqZACiQleuewkUi35E16wSd5C5QcnkkcV9cYc8TKPTRZlxappDuirxghxoOvFcJxFU4ixLsD
fN33jCHRoDUW81IH9zjij/vaw8IbVyb6vuwg6MX6inOEBRRzVbRYxXOu1wkWY6SsI8X70oF9aeLFp/PzQpjoe/YbSqpTq8qqrmHzn9vO+yvyYyvmDsphXe
X8f7fp9c7vUsfOCkM+gHY3PadG+QHa7KI7mzTKgUTZImK6BZtfRBATDTthEUbbaTewY4H0MnWiCeeDhcbeQao6cFy1To8pE3RpmxnGnS8BsBn8w=="""
INVALID_API_TOKEN = "invalid_key_123"
DATASET_NAME_LIMIT = 128
DOCUMENT_NAME_LIMIT = 255
CHAT_ASSISTANT_NAME_LIMIT = 255
SESSION_WITH_CHAT_NAME_LIMIT = 255

152
test/testcases/conftest.py Normal file
View File

@ -0,0 +1,152 @@
#
# 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.
#
import pytest
import requests
from configs import EMAIL, HOST_ADDRESS, PASSWORD, VERSION, ZHIPU_AI_API_KEY
MARKER_EXPRESSIONS = {
"p1": "p1",
"p2": "p1 or p2",
"p3": "p1 or p2 or p3",
}
def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption(
"--level",
action="store",
default="p2",
choices=list(MARKER_EXPRESSIONS.keys()),
help=f"Test level ({'/'.join(MARKER_EXPRESSIONS)}): p1=smoke, p2=core, p3=full",
)
parser.addoption(
"--client-type",
action="store",
default="http",
choices=["python_sdk", "http", "web"],
help="Test client type: 'python_sdk', 'http', 'web'",
)
def pytest_configure(config: pytest.Config) -> None:
level = config.getoption("--level")
config.option.markexpr = MARKER_EXPRESSIONS[level]
if config.option.verbose > 0:
print(f"\n[CONFIG] Active test level: {level}")
def register():
url = HOST_ADDRESS + f"/{VERSION}/user/register"
name = "qa"
register_data = {"email": EMAIL, "nickname": name, "password": PASSWORD}
res = requests.post(url=url, json=register_data)
res = res.json()
if res.get("code") != 0 and "has already registered" not in res.get("message"):
raise Exception(res.get("message"))
def login():
url = HOST_ADDRESS + f"/{VERSION}/user/login"
login_data = {"email": EMAIL, "password": PASSWORD}
response = requests.post(url=url, json=login_data)
res = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))
auth = response.headers["Authorization"]
return auth
@pytest.fixture(scope="session")
def auth():
try:
register()
except Exception as e:
print(e)
auth = login()
return auth
@pytest.fixture(scope="session")
def token(auth):
url = HOST_ADDRESS + f"/{VERSION}/system/new_token"
auth = {"Authorization": auth}
response = requests.post(url=url, headers=auth)
res = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))
return res["data"].get("token")
def get_my_llms(auth, name):
url = HOST_ADDRESS + f"/{VERSION}/llm/my_llms"
authorization = {"Authorization": auth}
response = requests.get(url=url, headers=authorization)
res = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))
if name in res.get("data"):
return True
return False
def add_models(auth):
url = HOST_ADDRESS + f"/{VERSION}/llm/set_api_key"
authorization = {"Authorization": auth}
models_info = {
"ZHIPU-AI": {"llm_factory": "ZHIPU-AI", "api_key": ZHIPU_AI_API_KEY},
}
for name, model_info in models_info.items():
if not get_my_llms(auth, name):
response = requests.post(url=url, headers=authorization, json=model_info)
res = response.json()
if res.get("code") != 0:
pytest.exit(f"Critical error in add_models: {res.get('message')}")
def get_tenant_info(auth):
url = HOST_ADDRESS + f"/{VERSION}/user/tenant_info"
authorization = {"Authorization": auth}
response = requests.get(url=url, headers=authorization)
res = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))
return res["data"].get("tenant_id")
@pytest.fixture(scope="session", autouse=True)
def set_tenant_info(auth):
try:
add_models(auth)
tenant_id = get_tenant_info(auth)
except Exception as e:
pytest.exit(f"Error in set_tenant_info: {str(e)}")
url = HOST_ADDRESS + f"/{VERSION}/user/set_tenant_info"
authorization = {"Authorization": auth}
tenant_info = {
"tenant_id": tenant_id,
"llm_id": "glm-4-flash@ZHIPU-AI",
"embd_id": "BAAI/bge-large-zh-v1.5@BAAI",
"img2txt_id": "",
"asr_id": "",
"tts_id": None,
}
response = requests.post(url=url, headers=authorization, json=tenant_info)
res = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))

View File

@ -0,0 +1,15 @@
#
# 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.
#

View File

@ -0,0 +1,34 @@
#
# 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 requests.auth import AuthBase
class RAGFlowHttpApiAuth(AuthBase):
def __init__(self, token):
self._token = token
def __call__(self, r):
r.headers["Authorization"] = f"Bearer {self._token}"
return r
class RAGFlowWebApiAuth(AuthBase):
def __init__(self, token):
self._token = token
def __call__(self, r):
r.headers["Authorization"] = self._token
return r

View File

@ -0,0 +1,63 @@
#
# 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.
#
import base64
import functools
import hashlib
import time
from pathlib import Path
def encode_avatar(image_path):
with Path.open(image_path, "rb") as file:
binary_data = file.read()
base64_encoded = base64.b64encode(binary_data).decode("utf-8")
return base64_encoded
def compare_by_hash(file1, file2, algorithm="sha256"):
def _calc_hash(file_path):
hash_func = hashlib.new(algorithm)
with open(file_path, "rb") as f:
while chunk := f.read(8192):
hash_func.update(chunk)
return hash_func.hexdigest()
return _calc_hash(file1) == _calc_hash(file2)
def wait_for(timeout=10, interval=1, error_msg="Timeout"):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
while True:
result = func(*args, **kwargs)
if result is True:
return result
elapsed = time.time() - start_time
if elapsed > timeout:
assert False, error_msg
time.sleep(interval)
return wrapper
return decorator
def is_sorted(data, field, descending=True):
timestamps = [ds[field] for ds in data]
return all(a >= b for a, b in zip(timestamps, timestamps[1:])) if descending else all(a <= b for a, b in zip(timestamps, timestamps[1:]))

View File

@ -0,0 +1,107 @@
#
# 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.
#
import json
from docx import Document # pip install python-docx
from openpyxl import Workbook # pip install openpyxl
from PIL import Image, ImageDraw # pip install Pillow
from pptx import Presentation # pip install python-pptx
from reportlab.pdfgen import canvas # pip install reportlab
def create_docx_file(path):
doc = Document()
doc.add_paragraph("This is a test DOCX file.")
doc.save(path)
return path
def create_excel_file(path):
wb = Workbook()
ws = wb.active
ws["A1"] = "Test Excel File"
wb.save(path)
return path
def create_ppt_file(path):
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[0])
slide.shapes.title.text = "Test PPT File"
prs.save(path)
return path
def create_image_file(path):
img = Image.new("RGB", (100, 100), color="blue")
draw = ImageDraw.Draw(img)
draw.text((10, 40), "Test", fill="white")
img.save(path)
return path
def create_pdf_file(path):
if not isinstance(path, str):
path = str(path)
c = canvas.Canvas(path)
c.drawString(100, 750, "Test PDF File")
c.save()
return path
def create_txt_file(path):
with open(path, "w", encoding="utf-8") as f:
f.write("This is the content of a test TXT file.")
return path
def create_md_file(path):
md_content = "# Test MD File\n\nThis is a test Markdown file."
with open(path, "w", encoding="utf-8") as f:
f.write(md_content)
return path
def create_json_file(path):
data = {"message": "This is a test JSON file", "value": 123}
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
return path
def create_eml_file(path):
eml_content = (
"From: sender@example.com\n"
"To: receiver@example.com\n"
"Subject: Test EML File\n\n"
"This is a test email content.\n"
)
with open(path, "w", encoding="utf-8") as f:
f.write(eml_content)
return path
def create_html_file(path):
html_content = (
"<html>\n"
"<head><title>Test HTML File</title></head>\n"
"<body><h1>This is a test HTML file</h1></body>\n"
"</html>"
)
with open(path, "w", encoding="utf-8") as f:
f.write(html_content)
return path

View File

@ -0,0 +1,28 @@
#
# 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.
#
import hypothesis.strategies as st
@st.composite
def valid_names(draw):
base_chars = "abcdefghijklmnopqrstuvwxyz_"
first_char = draw(st.sampled_from([c for c in base_chars if c.isalpha() or c == "_"]))
remaining = draw(st.text(alphabet=st.sampled_from(base_chars), min_size=0, max_size=128 - 2))
name = (first_char + remaining)[:128]
return name.encode("utf-8").decode("utf-8")