mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-11-02 04:43:27 +08:00
【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:
@@ -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 为非整数的错误信息"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user