[Tests] Add Qwen3 streaming parser delta boundary cases (#45708)

Signed-off-by: test test <2260891073@qq.com>

Palaiologos1453 committed Jun 19, 2026 at 01:37 UTC a0df04e4775efbfebd65c997259d63af0ec548ce
1 file changed +67
tests/tool_parsers/test_qwen3coder_tool_parser.py
+67
@@ -1300,6 +1300,73 @@ def test_streaming_multi_param_single_chunk(qwen3_tool_parser, qwen3_tokenizer):
1300 assert args["unit"] == "fahrenheit"
1301
1302
1303 +def test_streaming_complete_tool_call_single_delta(qwen3_tool_parser):
1304 + """Regression: one delta may contain a complete tool call."""
1305 + request = ChatCompletionRequest(model=MODEL, messages=[])
1306 +
1307 + from tests.tool_parsers.utils import (
1308 + run_tool_extraction_streaming,
1309 + )
1310 +
1311 + reconstructor = run_tool_extraction_streaming(
1312 + qwen3_tool_parser,
1313 + [
1314 + (
1315 + "<tool_call>\n"
1316 + "<function=get_current_weather>\n"
1317 + "<parameter=city>\nDallas\n</parameter>\n"
1318 + "<parameter=state>\nTX\n</parameter>\n"
1319 + "</function>\n"
1320 + "</tool_call>"
1321 + )
1322 + ],
1323 + request,
1324 + assert_one_tool_per_delta=False,
1325 + )
1326 +
1327 + assert len(reconstructor.tool_calls) == 1
1328 + assert reconstructor.tool_calls[0].function.name == "get_current_weather"
1329 + args = json.loads(reconstructor.tool_calls[0].function.arguments)
1330 + assert args == {"city": "Dallas", "state": "TX"}
1331 +
1332 +
1333 +def test_streaming_next_tool_call_starts_in_close_delta(qwen3_tool_parser):
1334 + """Regression: a close delta may also contain the next tool call."""
1335 + request = ChatCompletionRequest(model=MODEL, messages=[])
1336 +
1337 + from tests.tool_parsers.utils import (
1338 + run_tool_extraction_streaming,
1339 + )
1340 +
1341 + reconstructor = run_tool_extraction_streaming(
1342 + qwen3_tool_parser,
1343 + [
1344 + "<tool_call>\n",
1345 + "<function=get_current_weather>\n",
1346 + "<parameter=city>\nDallas\n</parameter>\n",
1347 + "<parameter=state>\nTX\n</parameter>\n",
1348 + "</function>",
1349 + (
1350 + "\n</tool_call>\n"
1351 + "<tool_call>\n"
1352 + "<function=get_current_weather>\n"
1353 + "<parameter=city>\nOrlando\n</parameter>\n"
1354 + "<parameter=state>\nFL\n</parameter>\n"
1355 + "</function>\n"
1356 + "</tool_call>"
1357 + ),
1358 + ],
1359 + request,
1360 + assert_one_tool_per_delta=False,
1361 + )
1362 +
1363 + assert len(reconstructor.tool_calls) == 2
1364 + first_args = json.loads(reconstructor.tool_calls[0].function.arguments)
1365 + second_args = json.loads(reconstructor.tool_calls[1].function.arguments)
1366 + assert first_args == {"city": "Dallas", "state": "TX"}
1367 + assert second_args == {"city": "Orlando", "state": "FL"}
1368 +
1369 +
1370 def test_no_double_serialization_string_args(qwen3_tool_parser):
1371 """Regression: string arguments must not be double-serialized (PR #35615)."""
1372 tools = [