[Config] Round 5.1: the published-side readers ask the bags, and a platform fact gets one address (#37086)

This commit is contained in:
Cheng Wan
2026-08-30 02:18:33 -07:00
committed by GitHub
parent a6e4021368
commit 7e751153eb
148 changed files with 1585 additions and 1114 deletions
@@ -55,10 +55,9 @@ def _accessor_names():
for node in tree.body
if isinstance(node, ast.FunctionDef) and node.name.startswith("get_")
}
# The context object itself is not a bag: it exists before anything is
# published, and `declare_late_resolution` calls it deliberately to find
# out whether the record it was handed has been published yet.
return frozenset(names - {"get_context"})
# Two that are not bags: the context object itself, and the platform facts.
# Both answer before anything is published.
return frozenset(names - {"get_context", "get_platform"})
_BAG_ACCESSORS = _accessor_names()
@@ -471,7 +471,7 @@ class TestResolutionReadsTheDeclarations(CustomTestCase):
members = _record_members()
# The floor is here to catch the scan collapsing, not to pin the
# class's size.
self.assertGreater(len(members), 25, f"only {len(members)} members were found")
self.assertGreater(len(members), 15, f"only {len(members)} members were found")
offenders = []
for name, fn in sorted(members.items()):
holders = _holders(fn) | {"self"}
@@ -73,7 +73,12 @@ from sglang.srt.model_executor.cuda_graph_config import (
Phase,
PhaseConfig,
)
from sglang.srt.runtime_context import get_context, get_serving
from sglang.srt.runtime_context import (
describe_kv_events_publisher,
get_context,
get_serving,
override_platform,
)
from sglang.srt.server_args import PortArgs, ServerArgs, prepare_server_args
from sglang.srt.utils.server_args_config_parser import ConfigArgumentMerger
from sglang.test.ci.ci_register import register_cpu_ci
@@ -333,8 +338,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
def _set_model_type(server_args, *, is_multimodal):
server_args._model_config = SimpleNamespace(is_multimodal=is_multimodal)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_cuda_ipc_is_explicit_and_bounded(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_cuda_ipc_is_explicit_and_bounded(self):
server_args = ServerArgs(
model_path="dummy",
mm_feature_transport="cuda_ipc",
@@ -355,8 +360,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
self.assertIn("base GPU 2", output)
self.assertIn("4 tokenizer worker", output)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_legacy_keep_flag_maps_to_cuda_ipc(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_legacy_keep_flag_maps_to_cuda_ipc(self):
server_args = ServerArgs(model_path="dummy", keep_mm_feature_on_device=True)
with patch.dict(os.environ, {"SGLANG_USE_CUDA_IPC_TRANSPORT": "0"}):
@@ -383,8 +388,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
with self.assertRaisesRegex(ValueError, "conflicts.*cuda_vmm"):
handle_multimodal_feature_transport(server_args)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_explicit_cpu_overrides_legacy_environment(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_explicit_cpu_overrides_legacy_environment(self):
server_args = ServerArgs(model_path="dummy", mm_feature_transport="cpu")
with patch.dict(os.environ, {"SGLANG_USE_CUDA_IPC_TRANSPORT": "1"}):
@@ -409,8 +414,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
)
self.assertFalse(envs.SGLANG_USE_CUDA_IPC_TRANSPORT.get())
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_default_transport_is_cpu_for_text_only_model(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_default_transport_is_cpu_for_text_only_model(self):
server_args = ServerArgs(model_path="dummy")
self._set_model_type(server_args, is_multimodal=False)
@@ -424,8 +429,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
)
self.assertFalse(envs.SGLANG_USE_CUDA_IPC_TRANSPORT.get())
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_default_transport_is_cpu_for_multimodal_model(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_default_transport_is_cpu_for_multimodal_model(self):
server_args = ServerArgs(model_path="dummy")
self._set_model_type(server_args, is_multimodal=True)
@@ -443,17 +448,13 @@ class TestMultimodalFeatureTransport(CustomTestCase):
@patch(
"sglang.srt.arg_groups.serving_hook.is_mnnvl_fabric_device", return_value=True
)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
@override_platform(is_cuda=True)
@patch(
"sglang.srt.model_loader.utils.supports_cuda_vmm_feature_transport",
return_value=True,
)
def test_default_transport_is_cuda_vmm_for_supported_multinode_mnnvl(
self,
_mock_supports_cuda_vmm,
_mock_is_cuda,
_mock_is_mnnvl,
_mock_path_exists,
self, _mock_supports_cuda_vmm, _mock_is_cuda, _mock_is_mnnvl
):
server_args = ServerArgs(model_path="dummy", nnodes=2)
self._set_model_type(server_args, is_multimodal=True)
@@ -476,17 +477,13 @@ class TestMultimodalFeatureTransport(CustomTestCase):
@patch(
"sglang.srt.arg_groups.serving_hook.is_mnnvl_fabric_device", return_value=True
)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
@override_platform(is_cuda=True)
@patch(
"sglang.srt.model_loader.utils.supports_cuda_vmm_feature_transport",
return_value=False,
)
def test_default_transport_is_cpu_for_unsupported_multinode_model(
self,
_mock_supports_cuda_vmm,
_mock_is_cuda,
_mock_is_mnnvl,
_mock_path_exists,
self, _mock_supports_cuda_vmm, _mock_is_cuda, _mock_is_mnnvl
):
server_args = ServerArgs(model_path="dummy", nnodes=2)
self._set_model_type(server_args, is_multimodal=True)
@@ -501,9 +498,9 @@ class TestMultimodalFeatureTransport(CustomTestCase):
@patch(
"sglang.srt.arg_groups.serving_hook.is_mnnvl_fabric_device", return_value=True
)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
@override_platform(is_cuda=True)
def test_default_transport_is_cpu_without_imex_channel(
self, _mock_is_cuda, _mock_is_mnnvl, _mock_path_exists
self, _mock_is_cuda, _mock_is_mnnvl
):
server_args = ServerArgs(model_path="dummy", nnodes=2)
self._set_model_type(server_args, is_multimodal=True)
@@ -522,10 +519,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
@patch(
"sglang.srt.arg_groups.serving_hook.is_mnnvl_fabric_device", return_value=False
)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_default_transport_is_cpu_for_multinode_non_mnnvl(
self, _mock_is_cuda, _mock_is_mnnvl
):
@override_platform(is_cuda=True)
def test_default_transport_is_cpu_for_multinode_non_mnnvl(self, _mock_is_cuda):
server_args = ServerArgs(model_path="dummy", nnodes=2)
self._set_model_type(server_args, is_multimodal=True)
@@ -538,8 +533,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
)
self.assertFalse(envs.SGLANG_USE_CUDA_IPC_TRANSPORT.get())
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_default_transport_is_cpu_for_language_only_model(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_default_transport_is_cpu_for_language_only_model(self):
server_args = ServerArgs(model_path="dummy", language_only=True)
self._set_model_type(server_args, is_multimodal=True)
@@ -552,15 +547,15 @@ class TestMultimodalFeatureTransport(CustomTestCase):
)
self.assertFalse(envs.SGLANG_USE_CUDA_IPC_TRANSPORT.get())
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=False)
def test_cuda_ipc_rejects_non_nvidia_platforms(self, _mock_is_cuda):
@override_platform(is_cuda=False)
def test_cuda_ipc_rejects_non_nvidia_platforms(self):
server_args = ServerArgs(model_path="dummy", mm_feature_transport="cuda_ipc")
with self.assertRaisesRegex(ValueError, "requires NVIDIA CUDA"):
handle_multimodal_feature_transport(server_args)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_cuda_ipc_rejects_multi_node(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_cuda_ipc_rejects_multi_node(self):
server_args = ServerArgs(
model_path="dummy", mm_feature_transport="cuda_ipc", nnodes=2
)
@@ -568,8 +563,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
with self.assertRaisesRegex(ValueError, "single node"):
handle_multimodal_feature_transport(server_args)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_cuda_vmm_is_explicit_and_uses_shared_budget(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_cuda_vmm_is_explicit_and_uses_shared_budget(self):
server_args = ServerArgs(
model_path="dummy",
mm_feature_transport="cuda_vmm",
@@ -595,15 +590,15 @@ class TestMultimodalFeatureTransport(CustomTestCase):
self.assertIn("2 tokenizer worker", output)
self.assertIn("falls back to inline CPU", output)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=False)
def test_cuda_vmm_rejects_non_nvidia_platforms(self, _mock_is_cuda):
@override_platform(is_cuda=False)
def test_cuda_vmm_rejects_non_nvidia_platforms(self):
server_args = ServerArgs(model_path="dummy", mm_feature_transport="cuda_vmm")
with self.assertRaisesRegex(ValueError, "requires NVIDIA CUDA"):
handle_multimodal_feature_transport(server_args)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_cuda_vmm_rejects_rust_server(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_cuda_vmm_rejects_rust_server(self):
server_args = ServerArgs(model_path="dummy", mm_feature_transport="cuda_vmm")
with (
@@ -612,8 +607,8 @@ class TestMultimodalFeatureTransport(CustomTestCase):
):
handle_multimodal_feature_transport(server_args)
@patch("sglang.srt.arg_groups.serving_hook.is_cuda", return_value=True)
def test_cuda_vmm_rejects_pipeline_parallelism(self, _mock_is_cuda):
@override_platform(is_cuda=True)
def test_cuda_vmm_rejects_pipeline_parallelism(self):
server_args = ServerArgs(
model_path="dummy", mm_feature_transport="cuda_vmm", pp_size=2
)
@@ -633,8 +628,8 @@ class TestMambaCacheStochasticRounding(unittest.TestCase):
with self.assertRaisesRegex(ValueError, "--mamba-ssm-dtype float16"):
handle_mamba_backend(server_args)
@patch("sglang.srt.arg_groups.mamba_hook.is_cuda", return_value=False)
def test_rejects_non_cuda(self, _mock_is_cuda):
@override_platform(is_cuda=False)
def test_rejects_non_cuda(self):
server_args = ServerArgs(
model_path="dummy",
mamba_ssm_dtype="float16",
@@ -644,9 +639,9 @@ class TestMambaCacheStochasticRounding(unittest.TestCase):
with self.assertRaisesRegex(ValueError, "NVIDIA CUDA"):
handle_mamba_backend(server_args)
@patch("sglang.srt.arg_groups.mamba_hook.is_cuda", return_value=True)
@patch("sglang.srt.arg_groups.mamba_hook.is_sm100_supported", return_value=False)
def test_rejects_triton_without_sm100(self, _mock_sm100, _mock_is_cuda):
@override_platform(is_cuda=True)
@override_platform(is_sm100=False)
def test_rejects_triton_without_sm100(self):
server_args = ServerArgs(
model_path="dummy",
mamba_ssm_dtype="float16",
@@ -832,8 +827,8 @@ class TestHiSparseDsaBackendPolicy(unittest.TestCase):
)
with (
patch("sglang.srt.configs.model_config.is_deepseek_dsa", return_value=True),
patch("sglang.srt.arg_groups.overrides.is_npu", return_value=False),
patch("sglang.srt.arg_groups.overrides.is_xpu", return_value=False),
override_platform(is_npu=False),
override_platform(is_xpu=False),
patch("torch.cuda.get_device_capability", return_value=(9, 0)),
):
declared = _dsa_split_backend_resolution(view)
@@ -846,22 +841,22 @@ class TestHiSparseDsaBackendPolicy(unittest.TestCase):
),
}
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=False)
def test_hisparse_defaults_to_flashmla_sparse_on_cuda_bfloat16(self, _mock_is_hip):
@override_platform(is_hip=False)
def test_hisparse_defaults_to_flashmla_sparse_on_cuda_bfloat16(self):
resolved = self._resolve("bfloat16")
self.assertEqual(resolved["dsa_prefill_backend"], "flashmla_sparse")
self.assertEqual(resolved["dsa_decode_backend"], "flashmla_sparse")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=False)
def test_hisparse_defaults_to_flashmla_kv_on_cuda_fp8(self, _mock_is_hip):
@override_platform(is_hip=False)
def test_hisparse_defaults_to_flashmla_kv_on_cuda_fp8(self):
resolved = self._resolve("fp8_e4m3")
self.assertEqual(resolved["dsa_prefill_backend"], "flashmla_kv")
self.assertEqual(resolved["dsa_decode_backend"], "flashmla_kv")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=False)
def test_hisparse_accepts_flashinfer_sparse_mla_on_cuda_fp8(self, _mock_is_hip):
@override_platform(is_hip=False)
def test_hisparse_accepts_flashinfer_sparse_mla_on_cuda_fp8(self):
"""SM120 GLM DSA resolves both DSA backends to flashinfer_sparse_mla, so
the fp8 hisparse allow-set must admit it or --enable-hisparse cannot
start there at all. The device/arch narrowing happens later, in
@@ -877,24 +872,22 @@ class TestHiSparseDsaBackendPolicy(unittest.TestCase):
validate_hisparse_dsa_backend(server_args, "dsa_prefill_backend", "prefill")
validate_hisparse_dsa_backend(server_args, "dsa_decode_backend", "decode")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=True)
def test_hisparse_defaults_to_tilelang_on_rocm(self, _mock_is_hip):
@override_platform(is_hip=True)
def test_hisparse_defaults_to_tilelang_on_rocm(self):
resolved = self._resolve("bfloat16")
self.assertEqual(resolved["dsa_prefill_backend"], "tilelang")
self.assertEqual(resolved["dsa_decode_backend"], "tilelang")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=True)
def test_hisparse_preserves_rocm_user_backend_and_defaults_missing_side(
self, _mock_is_hip
):
@override_platform(is_hip=True)
def test_hisparse_preserves_rocm_user_backend_and_defaults_missing_side(self):
resolved = self._resolve("bfloat16", dsa_prefill_backend="tilelang")
self.assertEqual(resolved["dsa_prefill_backend"], "tilelang")
self.assertEqual(resolved["dsa_decode_backend"], "tilelang")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=True)
def test_hisparse_accepts_aiter_backend_on_rocm(self, _mock_is_hip):
@override_platform(is_hip=True)
def test_hisparse_accepts_aiter_backend_on_rocm(self):
server_args = ServerArgs(
model_path="dummy",
enable_hisparse=True,
@@ -906,8 +899,8 @@ class TestHiSparseDsaBackendPolicy(unittest.TestCase):
validate_hisparse_dsa_backend(server_args, "dsa_prefill_backend", "prefill")
validate_hisparse_dsa_backend(server_args, "dsa_decode_backend", "decode")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=True)
def test_hisparse_rejects_cuda_backend_on_rocm(self, _mock_is_hip):
@override_platform(is_hip=True)
def test_hisparse_rejects_cuda_backend_on_rocm(self):
server_args = ServerArgs(
model_path="dummy",
enable_hisparse=True,
@@ -918,8 +911,8 @@ class TestHiSparseDsaBackendPolicy(unittest.TestCase):
with self.assertRaisesRegex(ValueError, "tilelang"):
validate_hisparse_dsa_backend(server_args, "dsa_prefill_backend", "prefill")
@patch("sglang.srt.arg_groups.hisparse_hook._is_hip", return_value=False)
def test_hisparse_rejects_rocm_backend_on_cuda(self, _mock_is_hip):
@override_platform(is_hip=False)
def test_hisparse_rejects_rocm_backend_on_cuda(self):
server_args = ServerArgs(
model_path="dummy",
enable_hisparse=True,
@@ -971,15 +964,15 @@ class TestFa4PageSizeAutoForce(CustomTestCase):
args.decode_attention_backend = decode
args.page_size = page_size
# Short-circuit model_config_of(): the fa4 page_size branch only needs
# use_mla_backend() (mocked) and is_sm100_supported() (mocked), not a
# use_mla_backend() (mocked) and override_platform(is_sm100=...), not a
# real model_config. Pre-set the attribute so get_model_config returns
# early without touching ModelConfig.from_server_args.
args._model_config = MagicMock()
args._model_config.hf_config.dual_chunk_attention_config = None
return args
@patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True)
def test_combined_attention_backend_fa4_forces_page_size_128(self, _mock_sm100):
@override_platform(is_sm100=True)
def test_combined_attention_backend_fa4_forces_page_size_128(self):
# `--attention-backend fa4` (combined): prefill/decode fields stay None.
args = self._make_args(attention_backend="fa4")
@@ -990,8 +983,8 @@ class TestFa4PageSizeAutoForce(CustomTestCase):
self.assertEqual(args.page_size, 1) # the field stays pristine
self.assertEqual(resolved_view(args).page_size, 128)
@patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True)
def test_explicit_prefill_fa4_forces_page_size_128(self, _mock_sm100):
@override_platform(is_sm100=True)
def test_explicit_prefill_fa4_forces_page_size_128(self):
# `--prefill-attention-backend fa4`: the previously-covered path.
args = self._make_args(attention_backend=None, prefill="fa4", page_size=1)
@@ -1969,11 +1962,11 @@ class TestPrefillCudaGraphLoRACompatibility(CustomTestCase):
prefill=PhaseConfig(backend=Backend.TC_PIECEWISE)
)
with (
patch("sglang.srt.arg_groups.cuda_graph_hook.is_hip", return_value=False),
patch("sglang.srt.arg_groups.cuda_graph_hook.is_npu", return_value=False),
override_platform(is_hip=False),
override_platform(is_npu=False),
patch("sglang.srt.arg_groups.cuda_graph_hook.is_cpu", return_value=False),
patch("sglang.srt.arg_groups.cuda_graph_hook.is_mps", return_value=False),
patch("sglang.srt.arg_groups.cuda_graph_hook.is_xpu", return_value=False),
override_platform(is_xpu=False),
):
disable_tc_piecewise_cudagraph_if_incompatible(args)
@@ -2602,15 +2595,27 @@ class TestGrpcServerArgs(CustomTestCase):
],
host="127.0.0.1",
)
# The port the sidecar dials is the resolved one, off the bag.
override = get_context_for_config().override_server_args(grpc_port=50051)
# Every value the sidecar reads is resolved config, so the case states
# them all through the context rather than half here and half in a
# stand-in the readers no longer consult.
override = get_context_for_config().override_server_args(
grpc_port=50051,
sidecar="example.sidecar",
sidecar_args=[
"--sidecar-shutdown-timeout",
"42",
"--grpc-connections",
"2",
],
host="127.0.0.1",
)
override.install()
self.addCleanup(override.restore)
with (
patch("sglang.srt.entrypoints.sidecar.mp.get_context") as get_context,
patch("sglang.srt.entrypoints.sidecar.Sidecar") as sidecar_class,
):
start_sidecar(server_args)
start_sidecar()
process_kwargs = get_context.return_value.Process.call_args.kwargs
self.assertEqual(process_kwargs["name"], "sglang_sidecar_example.sidecar")
@@ -2826,11 +2831,11 @@ class TestDcpKvEventContract(CustomTestCase):
page_size=64,
kv_events_config=self.KV_EVENTS,
)
self.assertEqual(args.describe_kv_events_publisher()["block_size"], 256)
self.assertEqual(describe_kv_events_publisher(args)["block_size"], 256)
args = ServerArgs(
model_path="dummy", page_size=64, kv_events_config=self.KV_EVENTS
)
self.assertEqual(args.describe_kv_events_publisher()["block_size"], 64)
self.assertEqual(describe_kv_events_publisher(args)["block_size"], 64)
def test_kv_event_block_size_widens_a_single_token_page(self):
# page_size=1 + DCP is a real deployment shape: the allocator is still