main
py 594 lines 24.2 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import os
5 from unittest.mock import patch
6
7 import pytest
8
9 import vllm.envs as envs
10 from vllm.envs import (
11 disable_envs_cache,
12 enable_envs_cache,
13 env_list_with_choices,
14 env_set_with_choices,
15 env_with_choices,
16 environment_variables,
17 )
18 from vllm.exceptions import VLLMValidationError
19
20
21 def test_object_storage_shm_default_name():
22 """The generated name must fit macOS's shared-memory name limit."""
23 assert len(envs._generate_shm_name()) <= 30
24
25
26 def test_getattr_without_cache(monkeypatch: pytest.MonkeyPatch):
27 assert envs.VLLM_HOST_IP == ""
28 assert envs.VLLM_PORT is None
29 monkeypatch.setenv("VLLM_HOST_IP", "1.1.1.1")
30 monkeypatch.setenv("VLLM_PORT", "1234")
31 assert envs.VLLM_HOST_IP == "1.1.1.1"
32 assert envs.VLLM_PORT == 1234
33 # __getattr__ is not decorated with functools.cache
34 assert not hasattr(envs.__getattr__, "cache_info")
35
36
37 def test_nixl_side_channel_host_is_not_compile_factor(
38 monkeypatch: pytest.MonkeyPatch,
39 ):
40 monkeypatch.setenv("VLLM_NIXL_SIDE_CHANNEL_HOST", "10.0.0.15")
41
42 assert "VLLM_NIXL_SIDE_CHANNEL_HOST" not in envs.compile_factors()
43
44
45 def test_api_key_is_not_compile_factor(monkeypatch: pytest.MonkeyPatch):
46 monkeypatch.setenv("VLLM_API_KEY", "sk-super-secret")
47
48 assert "VLLM_API_KEY" not in envs.compile_factors()
49
50
51 def test_p2p_side_channel_defaults_and_override(monkeypatch: pytest.MonkeyPatch):
52 monkeypatch.delenv("VLLM_P2P_SIDE_CHANNEL_HOST", raising=False)
53 monkeypatch.delenv("VLLM_P2P_SIDE_CHANNEL_PORT", raising=False)
54 assert envs.VLLM_P2P_SIDE_CHANNEL_HOST == "localhost"
55 assert envs.VLLM_P2P_SIDE_CHANNEL_PORT == 5710
56
57 monkeypatch.setenv("VLLM_P2P_SIDE_CHANNEL_HOST", "10.0.0.20")
58 monkeypatch.setenv("VLLM_P2P_SIDE_CHANNEL_PORT", "5799")
59 assert envs.VLLM_P2P_SIDE_CHANNEL_HOST == "10.0.0.20"
60 assert envs.VLLM_P2P_SIDE_CHANNEL_PORT == 5799
61
62
63 def test_getattr_with_cache(monkeypatch: pytest.MonkeyPatch):
64 monkeypatch.setenv("VLLM_HOST_IP", "1.1.1.1")
65 monkeypatch.setenv("VLLM_PORT", "1234")
66 # __getattr__ is not decorated with functools.cache
67 assert not hasattr(envs.__getattr__, "cache_info")
68
69 # Enable envs cache and ignore ongoing environment changes
70 enable_envs_cache()
71
72 # __getattr__ is decorated with functools.cache
73 assert hasattr(envs.__getattr__, "cache_info")
74 start_hits = envs.__getattr__.cache_info().hits
75
76 # 2 more hits due to VLLM_HOST_IP and VLLM_PORT accesses
77 assert envs.VLLM_HOST_IP == "1.1.1.1"
78 assert envs.VLLM_PORT == 1234
79 assert envs.__getattr__.cache_info().hits == start_hits + 2
80
81 # All environment variables are cached
82 for environment_variable in environment_variables:
83 envs.__getattr__(environment_variable)
84 assert envs.__getattr__.cache_info().hits == start_hits + 2 + len(
85 environment_variables
86 )
87
88 # Reset envs.__getattr__ back to none-cached version to
89 # avoid affecting other tests
90 envs.__getattr__ = envs.__getattr__.__wrapped__
91
92
93 def test_getattr_with_reset(monkeypatch: pytest.MonkeyPatch) -> None:
94 monkeypatch.setenv("VLLM_HOST_IP", "1.1.1.1")
95 # __getattr__ is not decorated with functools.cache
96 assert not hasattr(envs.__getattr__, "cache_info")
97
98 # Enable envs cache and ignore ongoing environment changes
99 enable_envs_cache()
100 assert envs.VLLM_HOST_IP == "1.1.1.1"
101 # With cache enabled, the environment variable value is cached and unchanged
102 monkeypatch.setenv("VLLM_HOST_IP", "2.2.2.2")
103 assert envs.VLLM_HOST_IP == "1.1.1.1"
104
105 disable_envs_cache()
106 assert envs.VLLM_HOST_IP == "2.2.2.2"
107 # After cache disabled, the environment variable value would be synced
108 # with os.environ
109 monkeypatch.setenv("VLLM_HOST_IP", "3.3.3.3")
110 assert envs.VLLM_HOST_IP == "3.3.3.3"
111
112
113 def test_is_envs_cache_enabled() -> None:
114 assert not envs._is_envs_cache_enabled()
115 enable_envs_cache()
116 assert envs._is_envs_cache_enabled()
117
118 # Only wrap one-layer of cache, so we only need to
119 # call disable once to reset.
120 enable_envs_cache()
121 enable_envs_cache()
122 enable_envs_cache()
123 disable_envs_cache()
124 assert not envs._is_envs_cache_enabled()
125
126 disable_envs_cache()
127 assert not envs._is_envs_cache_enabled()
128
129
130 def test_precompiled_install_flags_are_orthogonal() -> None:
131 # The Rust frontend flag is independent of the C-extension precompiled
132 # flag: requesting the precompiled Rust frontend must not implicitly
133 # enable the precompiled C extensions.
134 with patch.dict(os.environ, {"VLLM_USE_PRECOMPILED_RUST": "1"}, clear=True):
135 assert environment_variables["VLLM_USE_PRECOMPILED"]() is False
136 assert environment_variables["VLLM_USE_PRECOMPILED_RUST"]() is True
137
138 # ...and the reverse: requesting precompiled C extensions (here via a
139 # wheel location, which enables VLLM_USE_PRECOMPILED) must not flip the
140 # Rust frontend flag.
141 with patch.dict(
142 os.environ, {"VLLM_PRECOMPILED_WHEEL_LOCATION": "/tmp/vllm.whl"}, clear=True
143 ):
144 assert environment_variables["VLLM_USE_PRECOMPILED"]() is True
145 assert environment_variables["VLLM_USE_PRECOMPILED_RUST"]() is False
146
147 # ...and with both set together, each flag is still parsed independently.
148 with patch.dict(
149 os.environ,
150 {
151 "VLLM_PRECOMPILED_WHEEL_LOCATION": "/tmp/vllm.whl",
152 "VLLM_USE_PRECOMPILED_RUST": "1",
153 },
154 clear=True,
155 ):
156 assert environment_variables["VLLM_USE_PRECOMPILED"]() is True
157 assert environment_variables["VLLM_USE_PRECOMPILED_RUST"]() is True
158
159
160 def test_rust_bench_auto_path_missing_fails_fast() -> None:
161 with (
162 patch.dict(os.environ, {"VLLM_USE_RUST_BENCH": "1"}, clear=True),
163 patch("vllm.envs.os.path.isfile", return_value=False),
164 pytest.raises(FileNotFoundError, match="vllm-rs binary was not found"),
165 ):
166 environment_variables["VLLM_RUST_FRONTEND_PATH"]()
167
168
169 class TestEnvWithChoices:
170 """Test cases for env_with_choices function."""
171
172 def test_default_value_returned_when_env_not_set(self):
173 """Test default is returned when env var is not set."""
174 env_func = env_with_choices(
175 "NONEXISTENT_ENV", "default", ["option1", "option2"]
176 )
177 assert env_func() == "default"
178
179 def test_none_default_returned_when_env_not_set(self):
180 """Test that None is returned when env not set and default is None."""
181 env_func = env_with_choices("NONEXISTENT_ENV", None, ["option1", "option2"])
182 assert env_func() is None
183
184 def test_valid_value_returned_case_sensitive(self):
185 """Test that valid value is returned in case sensitive mode."""
186 with patch.dict(os.environ, {"TEST_ENV": "option1"}):
187 env_func = env_with_choices(
188 "TEST_ENV", "default", ["option1", "option2"], case_sensitive=True
189 )
190 assert env_func() == "option1"
191
192 def test_valid_lowercase_value_returned_case_insensitive(self):
193 """Test that lowercase value is accepted in case insensitive mode."""
194 with patch.dict(os.environ, {"TEST_ENV": "option1"}):
195 env_func = env_with_choices(
196 "TEST_ENV", "default", ["OPTION1", "OPTION2"], case_sensitive=False
197 )
198 assert env_func() == "option1"
199
200 def test_valid_uppercase_value_returned_case_insensitive(self):
201 """Test that uppercase value is accepted in case insensitive mode."""
202 with patch.dict(os.environ, {"TEST_ENV": "OPTION1"}):
203 env_func = env_with_choices(
204 "TEST_ENV", "default", ["option1", "option2"], case_sensitive=False
205 )
206 assert env_func() == "OPTION1"
207
208 def test_invalid_value_raises_error_case_sensitive(self):
209 """Test that invalid value raises ValueError in case sensitive mode."""
210 with patch.dict(os.environ, {"TEST_ENV": "invalid"}):
211 env_func = env_with_choices(
212 "TEST_ENV", "default", ["option1", "option2"], case_sensitive=True
213 )
214 with pytest.raises(
215 ValueError, match="Invalid value 'invalid' for TEST_ENV"
216 ):
217 env_func()
218
219 def test_case_mismatch_raises_error_case_sensitive(self):
220 """Test that case mismatch raises ValueError in case sensitive mode."""
221 with patch.dict(os.environ, {"TEST_ENV": "OPTION1"}):
222 env_func = env_with_choices(
223 "TEST_ENV", "default", ["option1", "option2"], case_sensitive=True
224 )
225 with pytest.raises(
226 ValueError, match="Invalid value 'OPTION1' for TEST_ENV"
227 ):
228 env_func()
229
230 def test_invalid_value_raises_error_case_insensitive(self):
231 """Test that invalid value raises ValueError when case insensitive."""
232 with patch.dict(os.environ, {"TEST_ENV": "invalid"}):
233 env_func = env_with_choices(
234 "TEST_ENV", "default", ["option1", "option2"], case_sensitive=False
235 )
236 with pytest.raises(
237 ValueError, match="Invalid value 'invalid' for TEST_ENV"
238 ):
239 env_func()
240
241 def test_callable_choices_resolved_correctly(self):
242 """Test that callable choices are resolved correctly."""
243
244 def get_choices():
245 return ["dynamic1", "dynamic2"]
246
247 with patch.dict(os.environ, {"TEST_ENV": "dynamic1"}):
248 env_func = env_with_choices("TEST_ENV", "default", get_choices)
249 assert env_func() == "dynamic1"
250
251 def test_callable_choices_with_invalid_value(self):
252 """Test that callable choices raise error for invalid values."""
253
254 def get_choices():
255 return ["dynamic1", "dynamic2"]
256
257 with patch.dict(os.environ, {"TEST_ENV": "invalid"}):
258 env_func = env_with_choices("TEST_ENV", "default", get_choices)
259 with pytest.raises(
260 ValueError, match="Invalid value 'invalid' for TEST_ENV"
261 ):
262 env_func()
263
264
265 def test_gdn_decode_kernel_env(monkeypatch: pytest.MonkeyPatch):
266 env_func = environment_variables["VLLM_GDN_DECODE_KERNEL"]
267 monkeypatch.delenv("VLLM_GDN_DECODE_KERNEL", raising=False)
268 assert env_func() == "cuda"
269
270 for value in ("cuda", "triton"):
271 monkeypatch.setenv("VLLM_GDN_DECODE_KERNEL", value)
272 assert env_func() == value
273
274 for value in ("fused", "invalid"):
275 monkeypatch.setenv("VLLM_GDN_DECODE_KERNEL", value)
276 with pytest.raises(ValueError, match="VLLM_GDN_DECODE_KERNEL"):
277 env_func()
278
279
280 class TestEnvListWithChoices:
281 """Test cases for env_list_with_choices function."""
282
283 def test_default_list_returned_when_env_not_set(self):
284 """Test that default list is returned when env var is not set."""
285 env_func = env_list_with_choices(
286 "NONEXISTENT_ENV", ["default1", "default2"], ["option1", "option2"]
287 )
288 assert env_func() == ["default1", "default2"]
289
290 def test_empty_default_list_returned_when_env_not_set(self):
291 """Test that empty default list is returned when env not set."""
292 env_func = env_list_with_choices("NONEXISTENT_ENV", [], ["option1", "option2"])
293 assert env_func() == []
294
295 def test_single_valid_value_parsed_correctly(self):
296 """Test that single valid value is parsed correctly."""
297 with patch.dict(os.environ, {"TEST_ENV": "option1"}):
298 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
299 assert env_func() == ["option1"]
300
301 def test_multiple_valid_values_parsed_correctly(self):
302 """Test that multiple valid values are parsed correctly."""
303 with patch.dict(os.environ, {"TEST_ENV": "option1,option2"}):
304 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
305 assert env_func() == ["option1", "option2"]
306
307 def test_values_with_whitespace_trimmed(self):
308 """Test that values with whitespace are trimmed correctly."""
309 with patch.dict(os.environ, {"TEST_ENV": " option1 , option2 "}):
310 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
311 assert env_func() == ["option1", "option2"]
312
313 def test_empty_values_filtered_out(self):
314 """Test that empty values are filtered out."""
315 with patch.dict(os.environ, {"TEST_ENV": "option1,,option2,"}):
316 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
317 assert env_func() == ["option1", "option2"]
318
319 def test_empty_string_returns_default(self):
320 """Test that empty string returns default."""
321 with patch.dict(os.environ, {"TEST_ENV": ""}):
322 env_func = env_list_with_choices(
323 "TEST_ENV", ["default"], ["option1", "option2"]
324 )
325 assert env_func() == ["default"]
326
327 def test_only_commas_returns_default(self):
328 """Test that string with only commas returns default."""
329 with patch.dict(os.environ, {"TEST_ENV": ",,,"}):
330 env_func = env_list_with_choices(
331 "TEST_ENV", ["default"], ["option1", "option2"]
332 )
333 assert env_func() == ["default"]
334
335 def test_case_sensitive_validation(self):
336 """Test case sensitive validation."""
337 with patch.dict(os.environ, {"TEST_ENV": "option1,OPTION2"}):
338 env_func = env_list_with_choices(
339 "TEST_ENV", [], ["option1", "option2"], case_sensitive=True
340 )
341 with pytest.raises(ValueError, match="Invalid value 'OPTION2' in TEST_ENV"):
342 env_func()
343
344 def test_case_insensitive_validation(self):
345 """Test case insensitive validation."""
346 with patch.dict(os.environ, {"TEST_ENV": "OPTION1,option2"}):
347 env_func = env_list_with_choices(
348 "TEST_ENV", [], ["option1", "option2"], case_sensitive=False
349 )
350 assert env_func() == ["OPTION1", "option2"]
351
352 def test_invalid_value_in_list_raises_error(self):
353 """Test that invalid value in list raises ValueError."""
354 with patch.dict(os.environ, {"TEST_ENV": "option1,invalid,option2"}):
355 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
356 with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
357 env_func()
358
359 def test_callable_choices_resolved_correctly(self):
360 """Test that callable choices are resolved correctly."""
361
362 def get_choices():
363 return ["dynamic1", "dynamic2"]
364
365 with patch.dict(os.environ, {"TEST_ENV": "dynamic1,dynamic2"}):
366 env_func = env_list_with_choices("TEST_ENV", [], get_choices)
367 assert env_func() == ["dynamic1", "dynamic2"]
368
369 def test_callable_choices_with_invalid_value(self):
370 """Test that callable choices raise error for invalid values."""
371
372 def get_choices():
373 return ["dynamic1", "dynamic2"]
374
375 with patch.dict(os.environ, {"TEST_ENV": "dynamic1,invalid"}):
376 env_func = env_list_with_choices("TEST_ENV", [], get_choices)
377 with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
378 env_func()
379
380 def test_duplicate_values_preserved(self):
381 """Test that duplicate values in the list are preserved."""
382 with patch.dict(os.environ, {"TEST_ENV": "option1,option1,option2"}):
383 env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
384 assert env_func() == ["option1", "option1", "option2"]
385
386
387 class TestEnvSetWithChoices:
388 """Test cases for env_set_with_choices function."""
389
390 def test_default_list_returned_when_env_not_set(self):
391 """Test that default list is returned when env var is not set."""
392 env_func = env_set_with_choices(
393 "NONEXISTENT_ENV", ["default1", "default2"], ["option1", "option2"]
394 )
395 assert env_func() == {"default1", "default2"}
396
397 def test_empty_default_list_returned_when_env_not_set(self):
398 """Test that empty default list is returned when env not set."""
399 env_func = env_set_with_choices("NONEXISTENT_ENV", [], ["option1", "option2"])
400 assert env_func() == set()
401
402 def test_single_valid_value_parsed_correctly(self):
403 """Test that single valid value is parsed correctly."""
404 with patch.dict(os.environ, {"TEST_ENV": "option1"}):
405 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
406 assert env_func() == {"option1"}
407
408 def test_multiple_valid_values_parsed_correctly(self):
409 """Test that multiple valid values are parsed correctly."""
410 with patch.dict(os.environ, {"TEST_ENV": "option1,option2"}):
411 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
412 assert env_func() == {"option1", "option2"}
413
414 def test_values_with_whitespace_trimmed(self):
415 """Test that values with whitespace are trimmed correctly."""
416 with patch.dict(os.environ, {"TEST_ENV": " option1 , option2 "}):
417 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
418 assert env_func() == {"option1", "option2"}
419
420 def test_empty_values_filtered_out(self):
421 """Test that empty values are filtered out."""
422 with patch.dict(os.environ, {"TEST_ENV": "option1,,option2,"}):
423 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
424 assert env_func() == {"option1", "option2"}
425
426 def test_empty_string_returns_default(self):
427 """Test that empty string returns default."""
428 with patch.dict(os.environ, {"TEST_ENV": ""}):
429 env_func = env_set_with_choices(
430 "TEST_ENV", ["default"], ["option1", "option2"]
431 )
432 assert env_func() == {"default"}
433
434 def test_only_commas_returns_default(self):
435 """Test that string with only commas returns default."""
436 with patch.dict(os.environ, {"TEST_ENV": ",,,"}):
437 env_func = env_set_with_choices(
438 "TEST_ENV", ["default"], ["option1", "option2"]
439 )
440 assert env_func() == {"default"}
441
442 def test_case_sensitive_validation(self):
443 """Test case sensitive validation."""
444 with patch.dict(os.environ, {"TEST_ENV": "option1,OPTION2"}):
445 env_func = env_set_with_choices(
446 "TEST_ENV", [], ["option1", "option2"], case_sensitive=True
447 )
448 with pytest.raises(ValueError, match="Invalid value 'OPTION2' in TEST_ENV"):
449 env_func()
450
451 def test_case_insensitive_validation(self):
452 """Test case insensitive validation."""
453 with patch.dict(os.environ, {"TEST_ENV": "OPTION1,option2"}):
454 env_func = env_set_with_choices(
455 "TEST_ENV", [], ["option1", "option2"], case_sensitive=False
456 )
457 assert env_func() == {"OPTION1", "option2"}
458
459 def test_invalid_value_in_list_raises_error(self):
460 """Test that invalid value in list raises ValueError."""
461 with patch.dict(os.environ, {"TEST_ENV": "option1,invalid,option2"}):
462 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
463 with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
464 env_func()
465
466 def test_callable_choices_resolved_correctly(self):
467 """Test that callable choices are resolved correctly."""
468
469 def get_choices():
470 return ["dynamic1", "dynamic2"]
471
472 with patch.dict(os.environ, {"TEST_ENV": "dynamic1,dynamic2"}):
473 env_func = env_set_with_choices("TEST_ENV", [], get_choices)
474 assert env_func() == {"dynamic1", "dynamic2"}
475
476 def test_callable_choices_with_invalid_value(self):
477 """Test that callable choices raise error for invalid values."""
478
479 def get_choices():
480 return ["dynamic1", "dynamic2"]
481
482 with patch.dict(os.environ, {"TEST_ENV": "dynamic1,invalid"}):
483 env_func = env_set_with_choices("TEST_ENV", [], get_choices)
484 with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
485 env_func()
486
487 def test_duplicate_values_deduped(self):
488 """Test that duplicate values in the list are deduped."""
489 with patch.dict(os.environ, {"TEST_ENV": "option1,option1,option2"}):
490 env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
491 assert env_func() == {"option1", "option2"}
492
493
494 class TestVllmConfigureLogging:
495 """Test cases for VLLM_CONFIGURE_LOGGING environment variable."""
496
497 def test_configure_logging_defaults_to_true(self):
498 """Test that VLLM_CONFIGURE_LOGGING defaults to True when not set."""
499 # Ensure the env var is not set
500 with patch.dict(os.environ, {}, clear=False):
501 if "VLLM_CONFIGURE_LOGGING" in os.environ:
502 del os.environ["VLLM_CONFIGURE_LOGGING"]
503
504 # Clear cache if it exists
505 if hasattr(envs.__getattr__, "cache_clear"):
506 envs.__getattr__.cache_clear()
507
508 result = envs.VLLM_CONFIGURE_LOGGING
509 assert result is True
510 assert isinstance(result, bool)
511
512 def test_configure_logging_with_zero_string(self):
513 """Test that VLLM_CONFIGURE_LOGGING='0' evaluates to False."""
514 with patch.dict(os.environ, {"VLLM_CONFIGURE_LOGGING": "0"}):
515 # Clear cache if it exists
516 if hasattr(envs.__getattr__, "cache_clear"):
517 envs.__getattr__.cache_clear()
518
519 result = envs.VLLM_CONFIGURE_LOGGING
520 assert result is False
521 assert isinstance(result, bool)
522
523 def test_configure_logging_with_one_string(self):
524 """Test that VLLM_CONFIGURE_LOGGING='1' evaluates to True."""
525 with patch.dict(os.environ, {"VLLM_CONFIGURE_LOGGING": "1"}):
526 # Clear cache if it exists
527 if hasattr(envs.__getattr__, "cache_clear"):
528 envs.__getattr__.cache_clear()
529
530 result = envs.VLLM_CONFIGURE_LOGGING
531 assert result is True
532 assert isinstance(result, bool)
533
534 def test_configure_logging_with_invalid_value_raises_error(self):
535 """Test that invalid VLLM_CONFIGURE_LOGGING value raises ValueError."""
536 with patch.dict(os.environ, {"VLLM_CONFIGURE_LOGGING": "invalid"}):
537 # Clear cache if it exists
538 if hasattr(envs.__getattr__, "cache_clear"):
539 envs.__getattr__.cache_clear()
540
541 with pytest.raises(ValueError, match="invalid literal for int"):
542 _ = envs.VLLM_CONFIGURE_LOGGING
543
544
545 class TestVllmMaxNSequences:
546 def test_default_value(self):
547 """Test that VLLM_MAX_N_SEQUENCES defaults to 64."""
548 with patch.dict(os.environ, {}, clear=False):
549 os.environ.pop("VLLM_MAX_N_SEQUENCES", None)
550 if hasattr(envs.__getattr__, "cache_clear"):
551 envs.__getattr__.cache_clear()
552
553 assert envs.VLLM_MAX_N_SEQUENCES == 16384
554
555 def test_custom_value(self, monkeypatch: pytest.MonkeyPatch):
556 """Test that VLLM_MAX_N_SEQUENCES can be overridden."""
557 monkeypatch.setenv("VLLM_MAX_N_SEQUENCES", "128")
558 if hasattr(envs.__getattr__, "cache_clear"):
559 envs.__getattr__.cache_clear()
560
561 assert envs.VLLM_MAX_N_SEQUENCES == 128
562
563 def test_sampling_params_respects_limit(
564 self,
565 monkeypatch: pytest.MonkeyPatch,
566 ):
567 """Test that SamplingParams rejects n above the limit."""
568 from vllm.sampling_params import SamplingParams
569
570 monkeypatch.delenv("VLLM_MAX_N_SEQUENCES", raising=False)
571 if hasattr(envs.__getattr__, "cache_clear"):
572 envs.__getattr__.cache_clear()
573
574 max_n = envs.VLLM_MAX_N_SEQUENCES
575 SamplingParams(n=max_n)
576
577 with pytest.raises(VLLMValidationError, match="n must be at most"):
578 SamplingParams(n=max_n + 1)
579
580 def test_sampling_params_respects_custom_limit(
581 self,
582 monkeypatch: pytest.MonkeyPatch,
583 ):
584 """Test that SamplingParams uses the overridden env var limit."""
585 from vllm.sampling_params import SamplingParams
586
587 monkeypatch.setenv("VLLM_MAX_N_SEQUENCES", "128")
588 if hasattr(envs.__getattr__, "cache_clear"):
589 envs.__getattr__.cache_clear()
590
591 SamplingParams(n=128)
592
593 with pytest.raises(VLLMValidationError, match="n must be at most 128"):
594 SamplingParams(n=129)