@@ -122,3 +122,332 @@ def test_stop_seq_exceed_length():
122
122
resp = send_request (URL , payload ).json ()
123
123
assert resp .get ("detail" ).get ("object" ) == "error" , "stop 超出长度应触发异常"
124
124
assert "exceeds the limit stop_seqs_max_len" in resp .get ("detail" ).get ("message" , "" ), "未返回预期的报错信息"
125
+
126
+
127
+ def test_multilingual_input ():
128
+ """测试多语言混合输入是否能够被正确处理"""
129
+ data = {
130
+ "messages" : [
131
+ {
132
+ "role" : "user" ,
133
+ "content" : "这是一个包含多种语言的输入:Hello, 世界!Bonjour, le monde! Hola, el mundo! こんにちは、世界!"
134
+ }
135
+ ],
136
+ "stream" : False ,
137
+
138
+ }
139
+ payload = build_request_payload (TEMPLATE , data )
140
+ resp = send_request (URL , payload ).json ()
141
+
142
+ # 验证响应是否包含有效的回复
143
+ assert "choices" in resp , "未收到有效的回复"
144
+ assert len (resp ["choices" ]) > 0 , "回复为空"
145
+ assert "message" in resp ["choices" ][0 ], "回复中未包含消息内容"
146
+ assert "content" in resp ["choices" ][0 ]["message" ], "回复中未包含内容字段"
147
+ # 验证模型是否能够正确处理多语言输入
148
+ response_content = resp ["choices" ][0 ]["message" ]["content" ]
149
+ assert response_content .strip () != "" , "模型未生成任何内容"
150
+ print ("多语言混合输入测试通过!" )
151
+
152
+
153
+
154
+ def test_too_long_input ():
155
+ """测试超长输入是否被正确处理"""
156
+ data = {
157
+ "messages" : [
158
+ {
159
+ "role" : "user" ,
160
+ "content" : "a," * 200000 # 超过最大输入长度
161
+ }
162
+ ],
163
+ "stream" : False
164
+ }
165
+ payload = build_request_payload (TEMPLATE , data )
166
+ resp = send_request (URL , payload ).json ()
167
+ assert resp ["detail" ].get ("object" ) == "error" , "超长输入未被识别为错误"
168
+ assert "Input text is too long" in resp ["detail" ].get ("message" , "" ), "未检测到最大长度限制错误"
169
+
170
+
171
+ def test_empty_input ():
172
+ """测试空输入是否被正确处理"""
173
+ data = {
174
+ "messages" : [
175
+ {
176
+ "role" : "user" ,
177
+ "content" : "" # 空输入
178
+ }
179
+ ],
180
+ "stream" : False
181
+ }
182
+ payload = build_request_payload (TEMPLATE , data )
183
+ resp = send_request (URL , payload ).json ()
184
+ assert "error" not in resp .get ("object" ), "空输入被识别为错误"
185
+ assert len (resp ["choices" ][0 ]["message" ]["content" ]) > 0 , "内容为空时,回复为空"
186
+
187
+
188
+ def test_prompt_only_spaces ():
189
+ """messages content 为纯空格字符串,服务正常返回"""
190
+ data = {
191
+ "messages" : [
192
+ {
193
+ "role" : "user" ,
194
+ "content" : " " , # 纯空格
195
+ }
196
+ ],
197
+ "stream" : False ,
198
+ "max_tokens" : 10 ,
199
+ }
200
+ payload = build_request_payload (TEMPLATE , data )
201
+ resp = send_request (URL , payload ).json ()
202
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
203
+ response_content = resp ["choices" ][0 ]["message" ]["content" ]
204
+ assert len (response_content ) > 0 , "messages content为空,未正常生成回复"
205
+
206
+
207
+ def test_illegal_characters ():
208
+ """测试非法字符输入是否被正确处理"""
209
+ data = {
210
+ "messages" : [
211
+ {
212
+ "role" : "user" ,
213
+ "content" : "非洲的首都是?:\x00 \x01 \x02 " # 非法字符
214
+ }
215
+ ],
216
+ "stream" : False
217
+ }
218
+ payload = build_request_payload (TEMPLATE , data )
219
+ resp = send_request (URL , payload ).json ()
220
+ assert len (resp ["choices" ][0 ]["message" ]["content" ]) > 0 , "非法字符输入影响模型回复"
221
+
222
+
223
+ def test_sql_injection ():
224
+ """测试 SQL 注入攻击是否被正确处理"""
225
+ data = {
226
+ "messages" : [
227
+ {
228
+ "role" : "user" ,
229
+ "content" : "SELECT * FROM users WHERE username = 'admin' OR '1'='1';" # SQL 注入攻击
230
+ }
231
+ ],
232
+ "stream" : False ,
233
+ "max_tokens" : 50 ,
234
+ }
235
+ payload = build_request_payload (TEMPLATE , data )
236
+ resp = send_request (URL , payload ).json ()
237
+ assert "message" in resp ["choices" ][0 ], "回复中未包含消息内容"
238
+ assert "content" in resp ["choices" ][0 ]["message" ], "回复中未包含内容字段"
239
+ response_content = resp ["choices" ][0 ]["message" ]["content" ]
240
+ assert len (response_content ) > 0 , "SQL 注入攻击影响模型回复"
241
+
242
+
243
+ def test_xss_attack ():
244
+ """测试 XSS 攻击是否被正确处理"""
245
+ data = {
246
+ "messages" : [
247
+ {
248
+ "role" : "user" ,
249
+ "content" : "<script>alert('XSS');</script>" # XSS 攻击
250
+ }
251
+ ],
252
+ "stream" : False ,
253
+ "max_tokens" : 50 ,
254
+ }
255
+ payload = build_request_payload (TEMPLATE , data )
256
+ resp = send_request (URL , payload ).json ()
257
+ assert "message" in resp ["choices" ][0 ], "回复中未包含消息内容"
258
+ assert "content" in resp ["choices" ][0 ]["message" ], "回复中未包含内容字段"
259
+ response_content = resp ["choices" ][0 ]["message" ]["content" ]
260
+ assert len (response_content ) > 0 , "XSS 攻击未被正确处理"
261
+
262
+
263
+ def test_stop_empty_string ():
264
+ """测试 stop 参数为空字符串时的行为"""
265
+ data = {
266
+ "stream" : False ,
267
+ "messages" : [
268
+ {
269
+ "role" : "user" ,
270
+ "content" : "非洲的首都是?"
271
+ }
272
+ ],
273
+ "max_tokens" : 10 ,
274
+ "stop" : "" # 空字符串
275
+ }
276
+ payload = build_request_payload (TEMPLATE , data )
277
+ resp = send_request (URL , payload ).json ()
278
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
279
+ assert len (resp .get ("choices" , [])[0 ].get ("message" , {}).get ("content" , "" )) > 0 , "应生成有效文本"
280
+
281
+
282
+ def test_stop_multiple_strings ():
283
+ """测试 stop 参数为多个字符串时的行为"""
284
+ data = {
285
+ "stream" : False ,
286
+ "messages" : [
287
+ {
288
+ "role" : "user" ,
289
+ "content" : "非洲的首都是?"
290
+ }
291
+ ],
292
+ "max_tokens" : 50 ,
293
+ "stop" : ["。" , "!" , "?" ] # 多个停止条件
294
+ }
295
+ payload = build_request_payload (TEMPLATE , data )
296
+ resp = send_request (URL , payload ).json ()
297
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
298
+ generated_text = resp .get ("choices" )[0 ].get ("message" , {}).get ("content" , "" )
299
+ assert any (stop in generated_text for stop in data ["stop" ]), "生成文本应包含 stop 序列之一"
300
+
301
+
302
+ def test_stop_with_special_characters ():
303
+ """测试 stop 参数为包含特殊字符的字符串时的行为"""
304
+ data = {
305
+ "stream" : False ,
306
+ "messages" : [
307
+ {
308
+ "role" : "user" ,
309
+ "content" : "非洲的首都是?"
310
+ }
311
+ ],
312
+ "max_tokens" : 50 ,
313
+ "stop" : "!@#$%^&*()" # 包含特殊字符
314
+ }
315
+ payload = build_request_payload (TEMPLATE , data )
316
+ resp = send_request (URL , payload ).json ()
317
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
318
+ generated_text = resp .get ("choices" )[0 ].get ("message" , {}).get ("content" , "" )
319
+ assert any (char in generated_text for char in data ["stop" ]), "生成文本应包含 stop 序列中的特殊字符之一"
320
+
321
+
322
+ def test_stop_with_newlines ():
323
+ """测试 stop 参数为包含换行符的字符串时的行为"""
324
+ data = {
325
+ "stream" : False ,
326
+ "messages" : [
327
+ {
328
+ "role" : "user" ,
329
+ "content" : "非洲的首都是?"
330
+ }
331
+ ],
332
+ "max_tokens" : 50 ,
333
+ "stop" : "\n \n " # 包含换行符
334
+ }
335
+ payload = build_request_payload (TEMPLATE , data )
336
+ resp = send_request (URL , payload ).json ()
337
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
338
+ generated_text = resp .get ("choices" )[0 ].get ("message" , {}).get ("content" , "" )
339
+ assert data ["stop" ] in generated_text , "生成文本应包含 stop 序列"
340
+
341
+
342
+ def test_model_empty ():
343
+ """model 参数为空,不影响服务"""
344
+ data = {
345
+ "messages" : [
346
+ {
347
+ "role" : "user" ,
348
+ "content" : "非洲的首都是?" ,
349
+ }
350
+ ],
351
+ "stream" : False ,
352
+ "max_tokens" : 10 ,
353
+ "model" : "" # 空模型
354
+ }
355
+ payload = build_request_payload (TEMPLATE , data )
356
+ resp = send_request (URL , payload ).json ()
357
+ assert resp .get ("object" ) == "chat.completion" , "应返回 chat.completion 对象"
358
+ response_content = resp ["choices" ][0 ]["message" ]["content" ]
359
+ assert len (response_content ) > 0 , "模型名为空,未正常生成回复"
360
+
361
+
362
+ def test_model_invalid ():
363
+ """model 参数为不存在的模型,不影响服务"""
364
+ data = {
365
+ "messages" : [
366
+ {
367
+ "role" : "user" ,
368
+ "content" : "非洲的首都是?" ,
369
+ }
370
+ ],
371
+ "stream" : False ,
372
+ "max_tokens" : 10 ,
373
+ "model" : "non-existent-model" # 不存在的模型
374
+ }
375
+ payload = build_request_payload (TEMPLATE , data )
376
+ resp = send_request (URL , payload ).json ()
377
+ assert resp .get ("object" ) == "chat.completion" , "不存在的 model 应触发校验异常"
378
+ assert "non-existent-model" in resp .get ("model" ), "未返回预期的 model 信息"
379
+ assert len (resp .get ("choices" )[0 ].get ("message" ).get ("content" )) > 0 , "模型名为不存在的 model,未正常生成回复"
380
+
381
+
382
+ def test_model_with_special_characters ():
383
+ """model 参数为非法格式(例如包含特殊字符),不影响服务"""
384
+ data = {
385
+ "messages" : [
386
+ {
387
+ "role" : "user" ,
388
+ "content" : "非洲的首都是?" ,
389
+ }
390
+ ],
391
+ "stream" : False ,
392
+ "max_tokens" : 10 ,
393
+ "model" : "!@#" # 包含特殊字符
394
+ }
395
+ payload = build_request_payload (TEMPLATE , data )
396
+ resp = send_request (URL , payload ).json ()
397
+ assert resp .get ("object" ) == "chat.completion" , "不存在的 model 应触发校验异常"
398
+ assert "!@#" in resp .get ("model" ), "未返回预期的 model 信息"
399
+ assert len (resp .get ("choices" )[0 ].get ("message" ).get ("content" )) > 0 , "模型名为model 参数为非法格式,未正常生成回复"
400
+
401
+
402
+ def test_max_tokens_negative ():
403
+ """max_tokens 为负数,服务应报错"""
404
+ data = {
405
+ "messages" : [
406
+ {
407
+ "role" : "user" ,
408
+ "content" : "非洲的首都是?" ,
409
+ }
410
+ ],
411
+ "stream" : False ,
412
+ "max_tokens" : - 10 , # 负数
413
+ }
414
+ payload = build_request_payload (TEMPLATE , data )
415
+ resp = send_request (URL , payload ).json ()
416
+ assert resp .get ("detail" ).get ("object" ) == "error" , "max_tokens < 0 未触发校验异常"
417
+ assert 'max_tokens can be defined [1,' in resp .get ("detail" ).get ("message" ), "未返回预期的 max_tokens 错误信息"
418
+
419
+
420
+ def test_max_tokens_min ():
421
+ """测试 max_tokens 达到异常值0 时的行为"""
422
+ data = {
423
+ "messages" : [
424
+ {
425
+ "role" : "user" ,
426
+ "content" : "非洲的首都是?" ,
427
+ }
428
+ ],
429
+ "stream" : False ,
430
+ "max_tokens" : 0 , # 最小值
431
+ }
432
+ payload = build_request_payload (TEMPLATE , data )
433
+ resp = send_request (URL , payload ).json ()
434
+ assert resp .get ('detail' ).get ("object" ) == "error" , "max_tokens未0时API未拦截住"
435
+ assert "reasoning_max_tokens must be between max_tokens and 1" in resp .get ('detail' ).get ("message" , "" ), "未返回预期的 max_tokens 达到异常值0 的 错误信息"
436
+
437
+
438
+ def test_max_tokens_non_integer ():
439
+ """max_tokens 为非整数,服务应报错"""
440
+ data = {
441
+ "messages" : [
442
+ {
443
+ "role" : "user" ,
444
+ "content" : "非洲的首都是?" ,
445
+ }
446
+ ],
447
+ "stream" : False ,
448
+ "max_tokens" : 10.5 , # 非整数
449
+ }
450
+ payload = build_request_payload (TEMPLATE , data )
451
+ resp = send_request (URL , payload ).json ()
452
+ assert resp .get ('detail' )[0 ].get ("msg" ) == "Input should be a valid integer, got a number with a fractional part" , "未返回预期的 max_tokens 为非整数的错误信息"
453
+
0 commit comments