main
py 102 lines 3.55 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import weakref
5 from unittest import mock
6
7 import pytest
8
9 from vllm import PoolingParams
10
11 MODEL_NAME = "intfloat/multilingual-e5-small"
12
13
14 @pytest.fixture(scope="module")
15 def llm(vllm_runner):
16 with vllm_runner(
17 MODEL_NAME,
18 max_model_len=None,
19 max_num_seqs=2, # small to trigger tiling
20 tensor_parallel_size=1,
21 gpu_memory_utilization=0.75,
22 enforce_eager=True,
23 seed=0,
24 enable_chunked_prefill=None,
25 ) as runner:
26 # pytest caches yielded fixtures until after teardown, so use a proxy to
27 # avoid retaining the LLM while VllmRunner.__exit__ releases ROCm memory.
28 yield weakref.proxy(runner.llm)
29
30
31 @pytest.mark.skip_global_cleanup
32 def test_tiling_engine_basic(llm):
33 """Basic test with a small number of prompts (less than max_num_seqs).
34 No tiling should be triggered, but the engine still processes correctly.
35 """
36 prompts = ["Hello", "World"]
37 outputs = llm.encode(prompts, pooling_task="embed")
38 assert len(outputs) == len(prompts)
39
40
41 @pytest.mark.skip_global_cleanup
42 def test_tiling_engine_many_requests(llm):
43 """Test with a large number of prompts that exceeds max_num_seqs.
44 This verifies that _run_tiling_engine correctly chunks requests,
45 processes all of them, and returns outputs in the correct order.
46 """
47 num_prompts = 10
48 prompts = [f"Prompt {i}" for i in range(num_prompts)]
49 outputs = llm.encode(prompts, pooling_task="embed")
50 assert len(outputs) == num_prompts
51
52
53 @pytest.mark.skip_global_cleanup
54 def test_tiling_engine_with_pooling_params(llm):
55 """Test the tiling engine when different PoolingParams are provided.
56 The engine must handle a list of params that matches the number of prompts.
57 """
58 num_prompts = 10
59 prompts = [f"Prompt {i}" for i in range(num_prompts)]
60 pooling_params = [PoolingParams() for _ in range(num_prompts)]
61
62 outputs = llm.encode(prompts, pooling_params=pooling_params, pooling_task="embed")
63 assert len(outputs) == num_prompts
64
65 # Single PoolingParams shared across all prompts
66 single_param = PoolingParams()
67 outputs = llm.encode(prompts, pooling_params=single_param, pooling_task="embed")
68 assert len(outputs) == num_prompts
69
70 # None PoolingParams should fall back to default
71 outputs = llm.encode(prompts, pooling_params=None, pooling_task="embed")
72 assert len(outputs) == num_prompts
73
74
75 @pytest.mark.skip_global_cleanup
76 def test_tiling_engine_abort_on_exception(llm):
77 """Test that abort_request IS called with the correct arguments when an
78 exception occurs inside the engine's step() loop.
79 """
80 prompts = ["Prompt 0", "Prompt 1", "Prompt 2"]
81
82 # Mock the step method to throw an exception on the second call
83 original_step = llm.llm_engine.step
84 call_count = 0
85
86 def mocked_step():
87 nonlocal call_count
88 call_count += 1
89 if call_count == 2:
90 raise RuntimeError("Simulated engine error")
91 return original_step()
92
93 with mock.patch.object(llm.llm_engine, "step", side_effect=mocked_step):
94 # We expect an exception to be raised from encode
95 with mock.patch.object(llm.llm_engine, "abort_request") as mock_abort: # noqa: SIM117
96 with pytest.raises(RuntimeError, match="Simulated engine error"):
97 llm.encode(prompts, pooling_task="embed")
98
99 args, kwargs = mock_abort.call_args
100 request_ids = args[0]
101 assert isinstance(request_ids, list)
102 assert len(request_ids) > 0