【CI】 evil case (#3359)

* Add ci case for min token and max token

* 【CI case】include total_tokens in the last packet of completion interface stream output

* 边缘检测 ,攻击性测试

* 边缘检测 ,攻击性测试

* 边缘检测 ,攻击性测试

* 边缘检测 ,攻击性测试

---------

Co-authored-by: xujing43 <xujing43@baidu.com>
This commit is contained in:
xjkmfa
2025-08-14 20:00:47 +08:00
committed by GitHub
parent cacc52bf21
commit ab60292f89

View File

@@ -122,3 +122,332 @@ def test_stop_seq_exceed_length():
resp = send_request(URL, payload).json()
assert resp.get("detail").get("object") == "error", "stop 超出长度应触发异常"
assert "exceeds the limit stop_seqs_max_len" in resp.get("detail").get("message", ""), "未返回预期的报错信息"
def test_multilingual_input():
"""测试多语言混合输入是否能够被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "这是一个包含多种语言的输入Hello, 世界Bonjour, le monde! Hola, el mundo! こんにちは、世界!"
}
],
"stream": False,
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
# 验证响应是否包含有效的回复
assert "choices" in resp, "未收到有效的回复"
assert len(resp["choices"]) > 0, "回复为空"
assert "message" in resp["choices"][0], "回复中未包含消息内容"
assert "content" in resp["choices"][0]["message"], "回复中未包含内容字段"
# 验证模型是否能够正确处理多语言输入
response_content = resp["choices"][0]["message"]["content"]
assert response_content.strip() != "", "模型未生成任何内容"
print("多语言混合输入测试通过!")
def test_too_long_input():
"""测试超长输入是否被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "a" * 200000 # 超过最大输入长度
}
],
"stream": False
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp["detail"].get("object") == "error", "超长输入未被识别为错误"
assert "Input text is too long" in resp["detail"].get("message", ""), "未检测到最大长度限制错误"
def test_empty_input():
"""测试空输入是否被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "" # 空输入
}
],
"stream": False
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert "error" not in resp.get("object"), "空输入被识别为错误"
assert len(resp["choices"][0]["message"]["content"]) > 0, "内容为空时,回复为空"
def test_prompt_only_spaces():
"""messages content 为纯空格字符串,服务正常返回"""
data = {
"messages": [
{
"role": "user",
"content": " ", # 纯空格
}
],
"stream": False,
"max_tokens": 10,
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
response_content = resp["choices"][0]["message"]["content"]
assert len(response_content) > 0, "messages content为空未正常生成回复"
def test_illegal_characters():
"""测试非法字符输入是否被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?:\x00\x01\x02" # 非法字符
}
],
"stream": False
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert len(resp["choices"][0]["message"]["content"]) > 0, "非法字符输入影响模型回复"
def test_sql_injection():
"""测试 SQL 注入攻击是否被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "SELECT * FROM users WHERE username = 'admin' OR '1'='1';" # SQL 注入攻击
}
],
"stream": False,
"max_tokens": 50,
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert "message" in resp["choices"][0], "回复中未包含消息内容"
assert "content" in resp["choices"][0]["message"], "回复中未包含内容字段"
response_content = resp["choices"][0]["message"]["content"]
assert len(response_content) > 0, "SQL 注入攻击影响模型回复"
def test_xss_attack():
"""测试 XSS 攻击是否被正确处理"""
data = {
"messages": [
{
"role": "user",
"content": "<script>alert('XSS');</script>" # XSS 攻击
}
],
"stream": False,
"max_tokens": 50,
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert "message" in resp["choices"][0], "回复中未包含消息内容"
assert "content" in resp["choices"][0]["message"], "回复中未包含内容字段"
response_content = resp["choices"][0]["message"]["content"]
assert len(response_content) > 0, "XSS 攻击未被正确处理"
def test_stop_empty_string():
"""测试 stop 参数为空字符串时的行为"""
data = {
"stream": False,
"messages": [
{
"role": "user",
"content": "非洲的首都是?"
}
],
"max_tokens": 10,
"stop": "" # 空字符串
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
assert len(resp.get("choices", [])[0].get("message", {}).get("content", "")) > 0, "应生成有效文本"
def test_stop_multiple_strings():
"""测试 stop 参数为多个字符串时的行为"""
data = {
"stream": False,
"messages": [
{
"role": "user",
"content": "非洲的首都是?"
}
],
"max_tokens": 50,
"stop": ["", "", ""] # 多个停止条件
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
generated_text = resp.get("choices")[0].get("message", {}).get("content", "")
assert any(stop in generated_text for stop in data["stop"]), "生成文本应包含 stop 序列之一"
def test_stop_with_special_characters():
"""测试 stop 参数为包含特殊字符的字符串时的行为"""
data = {
"stream": False,
"messages": [
{
"role": "user",
"content": "非洲的首都是?"
}
],
"max_tokens": 50,
"stop": "!@#$%^&*()" # 包含特殊字符
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
generated_text = resp.get("choices")[0].get("message", {}).get("content", "")
assert any(char in generated_text for char in data["stop"]), "生成文本应包含 stop 序列中的特殊字符之一"
def test_stop_with_newlines():
"""测试 stop 参数为包含换行符的字符串时的行为"""
data = {
"stream": False,
"messages": [
{
"role": "user",
"content": "非洲的首都是?"
}
],
"max_tokens": 50,
"stop": "\n\n" # 包含换行符
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
generated_text = resp.get("choices")[0].get("message", {}).get("content", "")
assert data["stop"] in generated_text, "生成文本应包含 stop 序列"
def test_model_empty():
"""model 参数为空,不影响服务"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": 10,
"model": "" # 空模型
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "应返回 chat.completion 对象"
response_content = resp["choices"][0]["message"]["content"]
assert len(response_content) > 0, "模型名为空,未正常生成回复"
def test_model_invalid():
"""model 参数为不存在的模型,不影响服务"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": 10,
"model": "non-existent-model" # 不存在的模型
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "不存在的 model 应触发校验异常"
assert "non-existent-model" in resp.get("model"), "未返回预期的 model 信息"
assert len(resp.get("choices")[0].get("message").get("content")) > 0, "模型名为不存在的 model未正常生成回复"
def test_model_with_special_characters():
"""model 参数为非法格式(例如包含特殊字符),不影响服务"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": 10,
"model": "!@#" # 包含特殊字符
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("object") == "chat.completion", "不存在的 model 应触发校验异常"
assert "!@#" in resp.get("model"), "未返回预期的 model 信息"
assert len(resp.get("choices")[0].get("message").get("content")) > 0, "模型名为model 参数为非法格式,未正常生成回复"
def test_max_tokens_negative():
"""max_tokens 为负数,服务应报错"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": -10, # 负数
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get("detail").get("object") == "error", "max_tokens < 0 未触发校验异常"
assert 'max_tokens can be defined [1,' in resp.get("detail").get("message"), "未返回预期的 max_tokens 错误信息"
def test_max_tokens_min():
"""测试 max_tokens 达到异常值0 时的行为"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": 0, # 最小值
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get('detail').get("object") == "error", "max_tokens未0时API未拦截住"
assert "reasoning_max_tokens must be between max_tokens and 1" in resp.get('detail').get("message", ""), "未返回预期的 max_tokens 达到异常值0 的 错误信息"
def test_max_tokens_non_integer():
"""max_tokens 为非整数,服务应报错"""
data = {
"messages": [
{
"role": "user",
"content": "非洲的首都是?",
}
],
"stream": False,
"max_tokens": 10.5, # 非整数
}
payload = build_request_payload(TEMPLATE, data)
resp = send_request(URL, payload).json()
assert resp.get('detail')[0].get("msg") == "Input should be a valid integer, got a number with a fractional part", "未返回预期的 max_tokens 为非整数的错误信息"