main
py 179 lines 4.56 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """E2E tests for render endpoints via `vllm launch` (GPU-less serving)."""
4
5 import httpx
6 import pytest
7 import pytest_asyncio
8
9 from tests.utils import RemoteLaunchRenderServer
10
11 MODEL_NAME = "hmellor/tiny-random-LlamaForCausalLM"
12
13
14 @pytest.fixture(scope="module")
15 def server():
16 args: list[str] = []
17 with RemoteLaunchRenderServer(MODEL_NAME, args, max_wait_seconds=120) as srv:
18 yield srv
19
20
21 @pytest_asyncio.fixture
22 async def client(server):
23 async with httpx.AsyncClient(
24 base_url=server.url_for(""), timeout=30.0
25 ) as http_client:
26 yield http_client
27
28
29 # -- Chat Completion Render --
30
31
32 @pytest.mark.asyncio
33 async def test_chat_render_basic(client):
34 response = await client.post(
35 "/v1/chat/completions/render",
36 json={
37 "model": MODEL_NAME,
38 "messages": [{"role": "user", "content": "Hello, how are you?"}],
39 },
40 )
41
42 assert response.status_code == 200
43 data = response.json()
44
45 # Response should be a GenerateRequest dict
46 assert isinstance(data, dict)
47 assert "token_ids" in data
48 assert isinstance(data["token_ids"], list)
49 assert len(data["token_ids"]) > 0
50 assert all(isinstance(t, int) for t in data["token_ids"])
51
52
53 @pytest.mark.asyncio
54 async def test_chat_render_multi_turn(client):
55 response = await client.post(
56 "/v1/chat/completions/render",
57 json={
58 "model": MODEL_NAME,
59 "messages": [
60 {"role": "user", "content": "Hello"},
61 {"role": "assistant", "content": "Hi there!"},
62 {"role": "user", "content": "How are you?"},
63 ],
64 },
65 )
66
67 assert response.status_code == 200
68 data = response.json()
69
70 assert isinstance(data, dict)
71 assert "token_ids" in data
72 assert isinstance(data["token_ids"], list)
73 assert len(data["token_ids"]) > 0
74
75
76 # -- Completion Render --
77
78
79 @pytest.mark.asyncio
80 async def test_completion_render_basic(client):
81 response = await client.post(
82 "/v1/completions/render",
83 json={
84 "model": MODEL_NAME,
85 "prompt": "Once upon a time",
86 },
87 )
88
89 assert response.status_code == 200
90 data = response.json()
91
92 assert isinstance(data, list)
93 assert len(data) > 0
94
95 first_prompt = data[0]
96 assert "token_ids" in first_prompt
97 assert "sampling_params" in first_prompt
98 assert "model" in first_prompt
99 assert "request_id" in first_prompt
100 assert isinstance(first_prompt["token_ids"], list)
101 assert len(first_prompt["token_ids"]) > 0
102 assert first_prompt["request_id"].startswith("cmpl-")
103
104
105 @pytest.mark.asyncio
106 async def test_completion_render_multiple_prompts(client):
107 response = await client.post(
108 "/v1/completions/render",
109 json={
110 "model": MODEL_NAME,
111 "prompt": ["Hello world", "Goodbye world"],
112 },
113 )
114
115 assert response.status_code == 200
116 data = response.json()
117
118 assert isinstance(data, list)
119 assert len(data) == 2
120
121 for prompt in data:
122 assert "token_ids" in prompt
123 assert "sampling_params" in prompt
124 assert "model" in prompt
125 assert "request_id" in prompt
126 assert len(prompt["token_ids"]) > 0
127 assert prompt["request_id"].startswith("cmpl-")
128
129
130 @pytest.mark.asyncio
131 async def test_completion_render_invalid_model(client):
132 response = await client.post(
133 "/v1/completions/render",
134 json={
135 "model": "nonexistent-model",
136 "prompt": "Hello",
137 },
138 )
139
140 assert response.status_code == 404
141 assert "error" in response.json()
142
143
144 @pytest.mark.asyncio
145 async def test_render_is_fast(client):
146 """Render should complete quickly since there is no inference."""
147 import time
148
149 start = time.perf_counter()
150 response = await client.post(
151 "/v1/completions/render",
152 json={
153 "model": MODEL_NAME,
154 "prompt": "Tell me a very long story about " * 10,
155 },
156 )
157 elapsed = time.perf_counter() - start
158
159 assert response.status_code == 200
160 assert elapsed < 2.0
161
162
163 # -- Health & Models --
164
165
166 @pytest.mark.asyncio
167 async def test_health_endpoint(client):
168 response = await client.get("/health")
169 assert response.status_code == 200
170
171
172 @pytest.mark.asyncio
173 async def test_models_endpoint(client):
174 response = await client.get("/v1/models")
175 assert response.status_code == 200
176 data = response.json()
177 assert "data" in data
178 model_ids = [m["id"] for m in data["data"]]
179 assert MODEL_NAME in model_ids