diff --git a/test/registered/unit/configs/test_linear_attn_model_registry.py b/test/registered/unit/configs/test_linear_attn_model_registry.py index 82c662c66c8a..785c73cde210 100644 --- a/test/registered/unit/configs/test_linear_attn_model_registry.py +++ b/test/registered/unit/configs/test_linear_attn_model_registry.py @@ -7,7 +7,6 @@ LinearAttnModelSpec, get_linear_attn_config, get_linear_attn_spec_by_arch, - import_backend_class, register_linear_attn_model, ) from sglang.test.ci.ci_register import register_cpu_ci @@ -138,24 +137,6 @@ def test_first_match_wins(self): result = get_linear_attn_config(FakeLinearAttnConfig()) self.assertIs(result[0], spec1) - def test_import_backend_class(self): - # Import a real stdlib class to verify the mechanism - cls = import_backend_class("collections.OrderedDict") - from collections import OrderedDict - - self.assertIs(cls, OrderedDict) - - def test_spec_defaults(self): - spec = LinearAttnModelSpec( - config_class=FakeLinearAttnConfig, - backend_class_name="pkg.mod.Cls", - ) - self.assertEqual(spec.arch_names, []) - self.assertTrue(spec.uses_mamba_radix_cache) - self.assertTrue(spec.support_mamba_cache) - self.assertFalse(spec.support_mamba_cache_extra_buffer) - self.assertFalse(spec.unwrap_text_config) - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/constrained/test_base_grammar_backend.py b/test/registered/unit/constrained/test_base_grammar_backend.py index 5fe364dccbcb..2c35e0763570 100644 --- a/test/registered/unit/constrained/test_base_grammar_backend.py +++ b/test/registered/unit/constrained/test_base_grammar_backend.py @@ -2,14 +2,10 @@ Unit tests for sglang.srt.constrained.base_grammar_backend. Test Coverage: -- GrammarStats: default values, mutable default isolation -- BaseGrammarObject: default behavior -- InvalidGrammarObject: error message - BaseGrammarBackend: caching, dispatch routing, unsupported fallback, thread pool execution, cache hit/miss - create_grammar_backend: factory routing, "none" backend, invalid name, custom registry, reasoner wrapping -- register_grammar_backend: registration and lookup Usage: python -m pytest test_base_grammar_backend.py -v @@ -36,44 +32,6 @@ register_cpu_ci(2.0, "base-a-test-cpu") -class TestGrammarStats(unittest.TestCase): - """Test GrammarStats dataclass.""" - - def test_defaults(self): - stats = GrammarStats() - self.assertIsNone(stats.compilation_time) - self.assertIsNone(stats.schema_count) - self.assertIsNone(stats.ebnf_size) - self.assertFalse(stats.is_cache_hit) - self.assertFalse(stats.is_grammar_aborted) - self.assertEqual(stats.tree_traversal_time, []) - self.assertIsNone(stats.dispatch_type) - self.assertEqual(stats.num_timeout, 0) - - def test_tree_traversal_time_mutable_default(self): - """Ensure each instance gets its own list.""" - s1 = GrammarStats() - s2 = GrammarStats() - s1.tree_traversal_time.append(0.1) - self.assertEqual(len(s2.tree_traversal_time), 0) - - -class TestBaseGrammarObject(unittest.TestCase): - """Test BaseGrammarObject base class.""" - - -class TestInvalidGrammarObject(unittest.TestCase): - """Test InvalidGrammarObject.""" - - def test_default_error_message(self): - obj = InvalidGrammarObject() - self.assertEqual(obj.error_message, "Unknown grammar error") - - def test_custom_error_message(self): - obj = InvalidGrammarObject("Regex compilation failed") - self.assertEqual(obj.error_message, "Regex compilation failed") - - class TestBaseGrammarBackend(unittest.TestCase): """Test BaseGrammarBackend caching and dispatch.""" @@ -206,24 +164,6 @@ def test_cache_miss_duplicate_key_submits_separate_futures(self): self.assertIsInstance(result2.result(timeout=5), InvalidGrammarObject) -class TestRegisterGrammarBackend(unittest.TestCase): - """Test grammar backend registry.""" - - def setUp(self): - self._saved = dict(GRAMMAR_BACKEND_REGISTRY) - - def tearDown(self): - GRAMMAR_BACKEND_REGISTRY.clear() - GRAMMAR_BACKEND_REGISTRY.update(self._saved) - - def test_overwrite_registration(self): - register_grammar_backend("dup", lambda *a: "first") - register_grammar_backend("dup", lambda *a: "second") - self.assertEqual( - GRAMMAR_BACKEND_REGISTRY["dup"](None, None, None, None), "second" - ) - - class TestCreateGrammarBackend(unittest.TestCase): """Test create_grammar_backend factory function.""" @@ -314,36 +254,6 @@ def test_custom_backend_skips_reasoner_wrapping(self): # Custom backends return early, no reasoner wrapping applied self.assertIs(result, mock_inner) - @patch("sglang.srt.constrained.outlines_backend.OutlinesGrammarBackend") - def test_outlines_backend(self, mock_outlines_cls): - mock_backend = MagicMock(spec=BaseGrammarBackend) - mock_outlines_cls.return_value = mock_backend - args = self._make_server_args( - "outlines", constrained_json_whitespace_pattern=r"\s*" - ) - - result = create_grammar_backend(args, "tok", 32000) - mock_outlines_cls.assert_called_once_with("tok", whitespace_pattern=r"\s*") - self.assertIs(result, mock_backend) - - @patch("sglang.srt.constrained.xgrammar_backend.XGrammarGrammarBackend") - def test_xgrammar_backend(self, mock_xgrammar_cls): - mock_backend = MagicMock(spec=BaseGrammarBackend) - mock_xgrammar_cls.return_value = mock_backend - args = self._make_server_args( - "xgrammar", constrained_json_disable_any_whitespace=True - ) - - result = create_grammar_backend(args, "tok", 32000, {1, 2}) - mock_xgrammar_cls.assert_called_once_with( - "tok", - vocab_size=32000, - model_eos_token_ids=[1, 2], - any_whitespace=False, - max_whitespace_cnt=None, - ) - self.assertIs(result, mock_backend) - @patch("sglang.srt.constrained.xgrammar_backend.XGrammarGrammarBackend") def test_xgrammar_unsupported_tokenizer_falls_back_to_none(self, mock_xgrammar_cls): from sglang.srt.constrained.xgrammar_backend import TokenizerNotSupportedError @@ -366,26 +276,6 @@ def test_xgrammar_unsupported_tokenizer_falls_back_to_none(self, mock_xgrammar_c # (asserted above). The two are meant to differ here. self.assertEqual(resolution_result(server_args, "grammar_backend"), "xgrammar") - @patch("sglang.srt.constrained.llguidance_backend.GuidanceBackend") - def test_llguidance_backend(self, mock_guidance_cls): - mock_backend = MagicMock(spec=BaseGrammarBackend) - mock_guidance_cls.return_value = mock_backend - args = self._make_server_args( - "llguidance", - constrained_json_disable_any_whitespace=False, - constrained_json_whitespace_pattern=r"\s+", - ) - - result = create_grammar_backend(args, "tok", 32000, {1, 2}) - mock_guidance_cls.assert_called_once_with( - tokenizer="tok", - any_whitespace=True, - whitespace_pattern=r"\s+", - n_vocab=32000, - eos_token_ids={1, 2}, - ) - self.assertIs(result, mock_backend) - @patch("sglang.srt.constrained.outlines_backend.OutlinesGrammarBackend") def test_reasoner_wrapping_on_builtin_backend(self, mock_outlines_cls): """Non-custom backends get wrapped with ReasonerGrammarBackend.""" diff --git a/test/registered/unit/constrained/test_grammar_manager.py b/test/registered/unit/constrained/test_grammar_manager.py index 9a6a96def486..25b989471774 100644 --- a/test/registered/unit/constrained/test_grammar_manager.py +++ b/test/registered/unit/constrained/test_grammar_manager.py @@ -111,18 +111,6 @@ def setUp(self): """Test GrammarManager initialization.""" - @patch("sglang.srt.constrained.grammar_manager.create_grammar_backend") - def test_init_with_backend(self, mock_create): - mock_create.return_value = MagicMock(spec=BaseGrammarBackend) - scheduler = _make_scheduler("xgrammar") - enter_override( - self, get_context().override_server_args(skip_tokenizer_init=False) - ) - - mgr = GrammarManager(scheduler) - self.assertIsNotNone(mgr.grammar_backend) - self.assertEqual(len(mgr), 0) - def test_init_skip_tokenizer(self): scheduler = _make_scheduler(skip_tokenizer=True) mgr = GrammarManager(scheduler) @@ -136,19 +124,6 @@ def test_len_and_has_waiting(self, mock_create): self.assertEqual(len(mgr), 0) self.assertFalse(mgr.has_waiting_grammars()) - @patch("sglang.srt.constrained.grammar_manager.create_grammar_backend") - def test_clear_resets_backend(self, mock_create): - mock_backend = MagicMock(spec=BaseGrammarBackend) - mock_create.return_value = mock_backend - scheduler = _make_scheduler() - enter_override( - self, get_context().override_server_args(skip_tokenizer_init=False) - ) - - mgr = GrammarManager(scheduler) - mgr.clear() - mock_backend.reset.assert_called_once() - @patch("sglang.srt.constrained.grammar_manager.create_grammar_backend") def test_clear_no_backend(self, mock_create): mock_create.return_value = None diff --git a/test/registered/unit/disaggregation/test_encode_server.py b/test/registered/unit/disaggregation/test_encode_server.py index 6f0c093dbf4f..134a75c14074 100644 --- a/test/registered/unit/disaggregation/test_encode_server.py +++ b/test/registered/unit/disaggregation/test_encode_server.py @@ -24,7 +24,6 @@ from sglang.srt.disaggregation.encoder.server import ( BadRequestError, EncodeContext, - EncoderDelivery, EncoderMetaRegistry, InternalError, MMEncoder, @@ -637,16 +636,6 @@ async def fail(): asyncio.run(run()) - def test_contract_has_two_direct_implementations(self): - self.assertEqual(EncoderDelivery.__abstractmethods__, {"send", "release"}) - self.assertEqual( - set(EncoderDelivery.__subclasses__()), - { - MooncakeDelivery, - ZmqDelivery, - }, - ) - def test_failed_staged_send_releases_request(self): async def run(): encoder = SimpleNamespace( diff --git a/test/registered/unit/disaggregation/test_fake_kv_sender.py b/test/registered/unit/disaggregation/test_fake_kv_sender.py index f8949bb9109f..dcaa5999115d 100644 --- a/test/registered/unit/disaggregation/test_fake_kv_sender.py +++ b/test/registered/unit/disaggregation/test_fake_kv_sender.py @@ -146,17 +146,6 @@ def test_abort_sets_failed_state(self): self.assertEqual(self.sender.conclude_state, KVPoll.Failed) self.assertEqual(self.sender.poll(), KVPoll.Failed) - def test_get_transfer_metric(self): - metric = self.sender.get_transfer_metric() - self.assertIsNone(metric.transfer_latency_s) - self.assertIsNone(metric.alloc_latency_s) - self.assertIsNone(metric.transfer_total_bytes) - - def test_failure_exception(self): - with self.assertRaises(Exception) as ctx: - self.sender.failure_exception() - self.assertIn("Fake KVSender Exception", str(ctx.exception)) - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/disaggregation/test_pd_role_switch.py b/test/registered/unit/disaggregation/test_pd_role_switch.py index 43498dca9792..629af34bcf0d 100644 --- a/test/registered/unit/disaggregation/test_pd_role_switch.py +++ b/test/registered/unit/disaggregation/test_pd_role_switch.py @@ -1,4 +1,3 @@ -import argparse import concurrent.futures import unittest from types import SimpleNamespace @@ -18,18 +17,6 @@ register_cpu_ci(est_time=5, suite="base-a-test-cpu") -class TestPdRoleSwitchServerArg(unittest.TestCase): - def test_cli_flag_parses(self): - parser = argparse.ArgumentParser() - ServerArgs.add_cli_args(parser) - - off = parser.parse_args(["--model-path", "dummy"]) - self.assertFalse(off.enable_pd_role_switch) - - on = parser.parse_args(["--model-path", "dummy", "--enable-pd-role-switch"]) - self.assertTrue(on.enable_pd_role_switch) - - class TestHandlePdRoleSwitch(unittest.TestCase): """Cover the control-plane contract of Scheduler.handle_pd_role_switch. @@ -388,14 +375,6 @@ def test_no_role_switch_is_unaffected(self): import zmq # noqa: E402 -try: - from sglang.srt.disaggregation.common.utils import FastQueue # noqa: E402 - from sglang.srt.disaggregation.mori.conn import MoriKVManager # noqa: E402 - - _HAS_MORI = True -except Exception: # pragma: no cover - environment dependent - _HAS_MORI = False - try: from sglang.srt.disaggregation.common.utils import ( # noqa: E402,F811 FastQueue as _FQ, @@ -417,38 +396,6 @@ def test_no_role_switch_is_unaffected(self): _HAS_ROLE_SWITCH = False -@unittest.skipUnless(_HAS_MORI, "mori not importable in this environment") -class TestMoriTeardownNoThreadLeak(unittest.TestCase): - """teardown() must stop+join the transfer workers it started, so a P->D->P - flip loop does not leak _num_shards transfer threads per cycle.""" - - def test_teardown_joins_transfer_workers(self): - m = MoriKVManager.__new__(MoriKVManager) - m.disaggregation_mode = DisaggregationMode.PREFILL - m._stopped = False - m._worker_threads = [] - m._transfer_queues = [FastQueue() for _ in range(3)] - m.server_socket = MagicMock() - m._zmq_ctx = MagicMock() - m.engine = MagicMock() - m.kv_mem_descs = m.aux_mem_descs = m.state_mem_descs = [] - for q in m._transfer_queues: - t = threading.Thread(target=m._transfer_worker, args=(q,), daemon=True) - t.start() - m._worker_threads.append(t) - started = list(m._worker_threads) - time.sleep(0.05) # let workers park in FastQueue.get() - for t in started: - self.assertTrue(t.is_alive()) - - MoriKVManager.teardown(m) - - for t in started: - self.assertFalse(t.is_alive(), "transfer worker survived teardown (leak)") - self.assertEqual(m._worker_threads, []) - self.assertEqual(m._transfer_queues, []) - - @unittest.skipUnless(_HAS_MOONCAKE, "mooncake not importable in this environment") class TestMooncakeTeardownNoThreadLeak(unittest.TestCase): """teardown() must stop+join the transfer workers it started, so a P->D->P diff --git a/test/registered/unit/entrypoints/openai/test_exa_search.py b/test/registered/unit/entrypoints/openai/test_exa_search.py index 8b7cb06b91f1..e45bcc7fe703 100644 --- a/test/registered/unit/entrypoints/openai/test_exa_search.py +++ b/test/registered/unit/entrypoints/openai/test_exa_search.py @@ -9,8 +9,6 @@ from sglang.srt.entrypoints.openai.tool_server import NativeToolServer from sglang.srt.entrypoints.search.exa_client import ( EXA_INTEGRATION_HEADER, - EXA_INTEGRATION_NAME, - ExaClient, ExaSearchConfig, ) from sglang.srt.entrypoints.tool import HarmonyBrowserTool @@ -20,33 +18,6 @@ class ExaClientTestCase(unittest.TestCase): - def test_headers_include_sglang_integration_tag(self): - client = ExaClient("test-key") - - headers = client._headers() - - self.assertEqual(headers["x-api-key"], "test-key") - self.assertEqual(headers[EXA_INTEGRATION_HEADER], EXA_INTEGRATION_NAME) - self.assertEqual(headers["Content-Type"], "application/json") - - def test_default_search_payload_uses_server_side_defaults(self): - client = ExaClient("test-key") - - payload = client._search_payload("SGLang native web search") - - self.assertEqual(payload["numResults"], 10) - self.assertEqual(payload["type"], "auto") - self.assertEqual(payload["contents"], {"highlights": True}) - - def test_contents_payload_requests_text_and_highlights(self): - client = ExaClient("test-key") - - payload = client._contents_payload(["https://example.com"]) - - self.assertEqual(payload["urls"], ["https://example.com"]) - self.assertTrue(payload["text"]) - self.assertTrue(payload["highlights"]) - def test_config_can_be_set_from_server_environment(self): env = { "SGLANG_EXA_NUM_RESULTS": "7", @@ -60,52 +31,6 @@ def test_config_can_be_set_from_server_environment(self): self.assertEqual(config.search_type, "fast") self.assertFalse(config.include_highlights) - def test_post_sends_integration_header_without_network(self): - captured = {} - - class FakeResponse: - status = 200 - - async def __aenter__(self): - return self - - async def __aexit__(self, *args): - return None - - async def text(self): - return '{"ok": true}' - - async def json(self): - return {"ok": True} - - class FakeSession: - def __init__(self, timeout): - captured["timeout"] = timeout - - async def __aenter__(self): - return self - - async def __aexit__(self, *args): - return None - - def post(self, url, json, headers): - captured["url"] = url - captured["json"] = json - captured["headers"] = headers - return FakeResponse() - - client = ExaClient("test-key") - with patch( - "sglang.srt.entrypoints.search.exa_client.aiohttp.ClientSession", - FakeSession, - ): - result = asyncio.run(client._post("/search", {"query": "sglang"})) - - self.assertEqual(result, {"ok": True}) - self.assertEqual(captured["url"], "https://api.exa.ai/search") - self.assertEqual(captured["json"], {"query": "sglang"}) - self.assertEqual(captured["headers"][EXA_INTEGRATION_HEADER], "sglang") - class ResponsesNativeWebSearchTestCase(unittest.TestCase): def test_harmony_web_search_requires_configured_backend(self): diff --git a/test/registered/unit/entrypoints/openai/test_protocol.py b/test/registered/unit/entrypoints/openai/test_protocol.py index fe312945c370..07cd4637bfed 100644 --- a/test/registered/unit/entrypoints/openai/test_protocol.py +++ b/test/registered/unit/entrypoints/openai/test_protocol.py @@ -30,7 +30,6 @@ CompletionRequest, Function, ModelCard, - ModelList, Tool, UsageInfo, ) @@ -51,27 +50,6 @@ def test_model_card_serialization(self): self.assertEqual(data["max_model_len"], 4096) -class TestModelList(unittest.TestCase): - """Test ModelList protocol model""" - - def test_empty_model_list(self): - """Test empty model list creation""" - model_list = ModelList() - self.assertEqual(model_list.object, "list") - self.assertEqual(len(model_list.data), 0) - - def test_model_list_with_cards(self): - """Test model list with model cards""" - cards = [ - ModelCard(id="model-1"), - ModelCard(id="model-2", max_model_len=2048), - ] - model_list = ModelList(data=cards) - self.assertEqual(len(model_list.data), 2) - self.assertEqual(model_list.data[0].id, "model-1") - self.assertEqual(model_list.data[1].id, "model-2") - - class TestCompletionRequest(unittest.TestCase): """Test CompletionRequest protocol model""" @@ -86,25 +64,6 @@ def test_basic_completion_request(self): self.assertFalse(request.stream) # default self.assertFalse(request.echo) # default - def test_completion_request_sglang_extensions(self): - """Test completion request with SGLang-specific extensions""" - request = CompletionRequest( - model="test-model", - prompt="Hello", - top_k=50, - min_p=0.1, - repetition_penalty=1.1, - regex=r"\d+", - json_schema='{"type": "object"}', - lora_path="/path/to/lora", - ) - self.assertEqual(request.top_k, 50) - self.assertEqual(request.min_p, 0.1) - self.assertEqual(request.repetition_penalty, 1.1) - self.assertEqual(request.regex, r"\d+") - self.assertEqual(request.json_schema, '{"type": "object"}') - self.assertEqual(request.lora_path, "/path/to/lora") - def test_completion_request_validation_errors(self): """Test completion request validation errors""" with self.assertRaises(ValidationError): @@ -239,38 +198,6 @@ def test_chat_completion_tool_choice_validation(self): ) self.assertEqual(request2.tool_choice, "auto") - def test_chat_completion_sglang_extensions(self): - """Test chat completion with SGLang extensions""" - messages = [{"role": "user", "content": "Hello"}] - request = ChatCompletionRequest( - model="test-model", - messages=messages, - top_k=40, - min_p=0.05, - separate_reasoning=False, - stream_reasoning=False, - chat_template_kwargs={"custom_param": "value"}, - ) - self.assertEqual(request.top_k, 40) - self.assertEqual(request.min_p, 0.05) - self.assertFalse(request.separate_reasoning) - self.assertFalse(request.stream_reasoning) - self.assertEqual(request.chat_template_kwargs, {"custom_param": "value"}) - - def test_chat_completion_tito_extensions(self): - """Test chat completion with pre-tokenized prompt extensions.""" - messages = [{"role": "user", "content": "Hello"}] - request = ChatCompletionRequest( - model="test-model", - messages=messages, - input_ids=[101, 102, 103], - return_prompt_token_ids=True, - return_meta_info=True, - ) - self.assertEqual(request.input_ids, [101, 102, 103]) - self.assertTrue(request.return_prompt_token_ids) - self.assertTrue(request.return_meta_info) - def test_chat_completion_reasoning_effort(self): """Test chat completion with reasoning effort""" messages = [{"role": "user", "content": "Hello"}] @@ -803,9 +730,5 @@ def test_negative_token_limits(self): CompletionRequest(model="test-model", prompt="Hello", max_tokens=-1) -class TestParsedResponseFieldsProtocol(unittest.TestCase): - """Test ParsedResponseFields protocol.""" - - if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/test/registered/unit/entrypoints/test_grpc_bridge.py b/test/registered/unit/entrypoints/test_grpc_bridge.py index b48abe8b9f1c..52fc3d78ab02 100644 --- a/test/registered/unit/entrypoints/test_grpc_bridge.py +++ b/test/registered/unit/entrypoints/test_grpc_bridge.py @@ -136,15 +136,6 @@ def test_observable_state_notifies_only_on_changes(self): self.manager.gracefully_exit = True self.assertEqual(self.notifications, 3) - def test_runtime_handle_registers_callback_with_manager(self): - handle = RuntimeHandle.__new__(RuntimeHandle) - handle.tokenizer_manager = self.manager - callback = object() - - handle.set_engine_state_changed_callback(callback) - - self.assertIs(self.manager._engine_state_changed_callback, callback) - def test_graceful_exit_notifies_and_changes_computed_health(self): handle = RuntimeHandle.__new__(RuntimeHandle) handle.tokenizer_manager = self.manager diff --git a/test/registered/unit/hardware_backend/mlx/test_fused_swiglu.py b/test/registered/unit/hardware_backend/mlx/test_fused_swiglu.py index 798f1c0ea9ee..62de2d4bb34d 100644 --- a/test/registered/unit/hardware_backend/mlx/test_fused_swiglu.py +++ b/test/registered/unit/hardware_backend/mlx/test_fused_swiglu.py @@ -1,31 +1,19 @@ -"""Numerical equivalence and eligibility tests for the Path B fused swiglu kernel. - -Two groups: - * Model-based equivalence (``@requires_model``): loads a small MoE model, runs - the fused gate_qmv + silu + ×x_up kernel against the unfused reference - (``mx.gather_qmm`` + ``nn.silu(gate) * x_up``) on both the unsorted and - sorted paths. Gated by SGLANG_MLX_TEST_MODEL so CI hosts without a model - cache skip them (stage-a sets HF_HUB_OFFLINE=1, so they stay skipped there). - * Synthetic eligibility (no model, MLX only): the learned-bias fallback. The - fused kernel recomputes the gate matmul and has no slot for the per-expert - learned bias QuantizedSwitchLinear adds after the matmul, so ``can_fuse`` - must exclude a gate carrying one, and the patch must leave such a layer - unfused. These run wherever MLX is available (Apple Silicon). - -Registered on the CPU suite but skipped wherever mlx is absent; runs for real -only on Apple Silicon via stage-a-unit-test-mlx. +"""Eligibility tests for the Path B fused swiglu kernel. + +The fused kernel recomputes the gate matmul and has no slot for the per-expert +learned bias QuantizedSwitchLinear adds after the matmul, so ``can_fuse`` must +exclude a gate carrying one, and the patch must leave such a layer unfused. +Runs only on Apple Silicon with MLX, via stage-a-unit-test-mlx. """ import importlib.util -import os import platform import sys import pytest -from sglang.test.ci.ci_register import register_cpu_ci, register_mlx_ci +from sglang.test.ci.ci_register import register_mlx_ci -register_cpu_ci(est_time=7, suite="base-a-test-cpu") register_mlx_ci(est_time=45, suite="stage-a-unit-test-mlx") _IS_APPLE_SILICON = platform.system() == "Darwin" and platform.machine() == "arm64" @@ -46,13 +34,6 @@ import mlx.core as mx -# Model-based tests need a real checkpoint; synthetic tests below do not. -requires_model = pytest.mark.skipif( - not os.environ.get("SGLANG_MLX_TEST_MODEL"), - reason="Set SGLANG_MLX_TEST_MODEL to a HuggingFace model id to enable", -) - - def _max_rel_diff(a, b): diff = mx.abs(a.astype(mx.float32) - b.astype(mx.float32)) max_abs = diff.max().item() @@ -60,89 +41,6 @@ def _max_rel_diff(a, b): return max_abs, max_abs / max(ref_max, 1e-9) -@requires_model -def test_fused_gate_qmv_silu_mul_matches_unfused(): - """Kernel output matches ``nn.silu(gate_qmv) * x_up`` within bf16 ULP.""" - import mlx.nn as nn - from mlx_lm import load - - from sglang.srt.hardware_backend.mlx.moe.fused_swiglu import ( - can_fuse, - fused_gate_qmv_silu_mul, - ) - - model, _ = load(os.environ["SGLANG_MLX_TEST_MODEL"]) - sw = model.model.layers[0].mlp.switch_mlp - assert can_fuse(sw), "layer 0 not eligible for fused swiglu" - - up = sw.up_proj - gate = sw.gate_proj - in_dim = up.scales.shape[-1] * up.group_size - out_dim = up.weight.shape[-2] - num_experts = up.weight.shape[0] - dtype = up.scales.dtype - - # Two batch sizes both take the unsorted path (indices.size < 64). - for B, TOPK in [(1, 8), (4, 8)]: - x = mx.random.normal(shape=(B, 1, 1, in_dim)).astype(dtype) - indices = mx.random.randint(0, num_experts, shape=(B, TOPK)).astype(mx.uint32) - - x_up = up(x, indices, sorted_indices=False) - x_gate = gate(x, indices, sorted_indices=False) - y_ref = nn.silu(x_gate) * x_up - - y_fused = fused_gate_qmv_silu_mul( - x, gate["weight"], gate["scales"], gate.get("biases"), indices, x_up - ) - mx.eval(y_ref, y_fused) - - assert y_ref.shape == y_fused.shape - - max_abs, rel = _max_rel_diff(y_ref, y_fused) - # 2 % relative covers ~2 bf16 ULPs at typical activation magnitudes; - # the kernel's fp32 accumulation order matches MLX's qmv_fast_impl so - # most elements should land within 1 ULP. - assert rel < 2e-2, f"B={B} TOPK={TOPK}: max_abs={max_abs:.3e} rel={rel:.2%}" - - -@requires_model -def test_patched_switchglu_matches_unpatched(): - """Full SwitchGLU forward equivalence on both sorted and unsorted paths.""" - from mlx_lm import load - - from sglang.srt.hardware_backend.mlx.moe.fused_swiglu import ( - patch_switch_glu_with_fused_swiglu, - ) - - model, _ = load(os.environ["SGLANG_MLX_TEST_MODEL"]) - sw = model.model.layers[0].mlp.switch_mlp - in_dim = sw.up_proj.scales.shape[-1] * sw.up_proj.group_size - num_experts = sw.up_proj.weight.shape[0] - dtype = sw.up_proj.scales.dtype - - cases = [] - # B=2 TOPK=8 -> indices.size=16 < 64 -> unsorted - # B=8 TOPK=8 -> indices.size=64 -> sorted - for B, TOPK, label in [(2, 8, "unsorted"), (8, 8, "sorted")]: - x = mx.random.normal(shape=(B, in_dim)).astype(dtype) - indices = mx.random.randint(0, num_experts, shape=(B, TOPK)).astype(mx.uint32) - out_ref = sw(x, indices) - mx.eval(out_ref) - cases.append((label, x, indices, out_ref)) - - n_patched = patch_switch_glu_with_fused_swiglu(model) - assert n_patched > 0, "no SwitchGLU layers were patched" - - for label, x, indices, out_ref in cases: - out_fused = sw(x, indices) - mx.eval(out_fused) - max_abs, rel = _max_rel_diff(out_ref, out_fused) - # 5 % is generous; in practice we see <0.6 % on 48-layer Qwen3-MoE. - # The looser bound here absorbs cross-layer ULP propagation through - # down_proj's quantized matmul. - assert rel < 5e-2, f"full forward {label}: max_abs={max_abs:.3e} rel={rel:.2%}" - - # Learned-bias fallback (synthetic, no model): a gate with a learned bias must # not fuse, since the kernel has no slot for the bias added after the matmul. def _quantized_switch_glu(in_dim, hidden, n_experts, gate_bias): @@ -254,7 +152,6 @@ def test_fused_matches_unfused_synthetic(): assert bool(mx.all(mx.isfinite(y_fused.astype(mx.float32))).item()), ( f"B={B} hi={hi}: non-finite fused output" ) - # Same bf16 bound as the @requires_model kernel test. max_abs, rel = _max_rel_diff(y_ref, y_fused) assert rel < 2e-2, f"B={B} hi={hi}: max_abs={max_abs:.3e} rel={rel:.2%}" diff --git a/test/registered/unit/hardware_backend/mlx/test_metal_profiler.py b/test/registered/unit/hardware_backend/mlx/test_metal_profiler.py index 97c8bb412482..b559d4206843 100644 --- a/test/registered/unit/hardware_backend/mlx/test_metal_profiler.py +++ b/test/registered/unit/hardware_backend/mlx/test_metal_profiler.py @@ -18,7 +18,7 @@ import tempfile import unittest from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import patch from sglang.srt.runtime_context import get_parallel from sglang.test.ci.ci_register import register_mlx_ci @@ -141,50 +141,6 @@ def test_stop_calls_stop_capture(self): mock_stop.assert_called_once() -@unittest.skipUnless(_IS_APPLE_SILICON and _HAS_MLX, _SKIP_REASON) -class TestMetalCaptureProfilerMPS(unittest.TestCase): - """MPS path: start_mps wraps torch.mps.profiler.metal_capture.""" - - def test_start_mps_success(self): - import torch - - from sglang.srt.hardware_backend.mlx.profiler import MetalCaptureProfiler - - mock_ctx = MagicMock() - mock_ctx.__enter__ = MagicMock(return_value=mock_ctx) - mock_ctx.__exit__ = MagicMock(return_value=False) - - with tempfile.TemporaryDirectory() as tmp: - trace_path = Path(tmp) / "test.gputrace" - with patch.object( - torch.mps.profiler, "metal_capture", return_value=mock_ctx - ): - profiler, result = MetalCaptureProfiler.start_mps(trace_path) - - self.assertTrue(result.success) - self.assertIsNotNone(profiler) - self.assertEqual(profiler.label, "MPS") - self.assertFalse(profiler.standalone) - - def test_start_mps_runtime_error_returns_failure(self): - import torch - - from sglang.srt.hardware_backend.mlx.profiler import MetalCaptureProfiler - - with tempfile.TemporaryDirectory() as tmp: - trace_path = Path(tmp) / "test.gputrace" - with patch.object( - torch.mps.profiler, - "metal_capture", - side_effect=RuntimeError("MPS profiler unavailable"), - ): - profiler, result = MetalCaptureProfiler.start_mps(trace_path) - - self.assertIsNone(profiler) - self.assertFalse(result.success) - self.assertIn("MTL_CAPTURE_ENABLED", result.message) - - @unittest.skipUnless(_IS_APPLE_SILICON and _HAS_MLX, _SKIP_REASON) class TestSchedulerProfilerManagerMPS(unittest.TestCase): """SchedulerProfilerManager._start_profile handles Metal capture failures. diff --git a/test/registered/unit/layers/attention/test_fp8_fused_writer_hip.py b/test/registered/unit/layers/attention/test_fp8_fused_writer_hip.py index 0149841bb08d..7e9bc100a42d 100644 --- a/test/registered/unit/layers/attention/test_fp8_fused_writer_hip.py +++ b/test/registered/unit/layers/attention/test_fp8_fused_writer_hip.py @@ -1,7 +1,5 @@ -import sys -import types import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import patch import torch @@ -59,43 +57,6 @@ def _inputs(self): sin_cache=torch.empty(1024, 32, dtype=torch.bfloat16), ) - def test_forwards_full_abi(self): - op = MagicMock() - cache_module = types.ModuleType("aiter.ops.cache") - cache_module.indexer_qk_rope_quant_and_cache = op - ops_module = types.ModuleType("aiter.ops") - ops_module.cache = cache_module - aiter_module = types.ModuleType("aiter") - aiter_module.ops = ops_module - - args = self._inputs() - with patch.dict( - sys.modules, - { - "aiter": aiter_module, - "aiter.ops": ops_module, - "aiter.ops.cache": cache_module, - }, - ): - aiter_fused_fp8_qk_write( - **args, - epsilon=1e-6, - quant_block_size=128, - scale_fmt="ue8m0", - weights_scale=0.03125, - preshuffle=True, - is_neox=False, - compute_all_q_rope=True, - ) - - op.assert_called_once() - call = op.call_args - self.assertIs(call.args[0], args["q"]) - self.assertIs(call.args[5], args["kv_cache"]) - self.assertEqual(call.kwargs["preshuffle"], True) - self.assertEqual(call.kwargs["is_neox"], False) - self.assertEqual(call.kwargs["compute_all_q_rope"], True) - def test_refuses_non_fp32_layernorm(self): args = self._inputs() args["norm_weight"] = args["norm_weight"].bfloat16() diff --git a/test/registered/unit/layers/attention/test_kda_helion_dispatcher.py b/test/registered/unit/layers/attention/test_kda_helion_dispatcher.py index e9f64642347f..1ce62a3df4e6 100644 --- a/test/registered/unit/layers/attention/test_kda_helion_dispatcher.py +++ b/test/registered/unit/layers/attention/test_kda_helion_dispatcher.py @@ -81,11 +81,6 @@ def test_prefill_only_keeps_triton_decode_and_verify(self): self.assertIs(dispatcher.extend_kernel, helion_kernel) self.assertIsInstance(dispatcher.verify_kernel, TritonKDAKernel) - def test_enum_recognizes_helion(self): - backend = LinearAttnKernelBackend("helion") - self.assertIs(backend, LinearAttnKernelBackend.HELION) - self.assertTrue(backend.is_helion()) - def test_replayssm_decode_uses_native_helion_kernel(self): kernel = HelionKDAKernel.__new__(HelionKDAKernel) kernel._packed_decode = MagicMock() @@ -129,35 +124,6 @@ def test_replayssm_decode_uses_native_helion_kernel(self): self.assertEqual(kernel._replayssm_decode.call_args.kwargs["lower_bound"], -5.0) kernel._triton.packed_decode.assert_not_called() - def test_packed_decode_forwards_lower_bound(self): - kernel = HelionKDAKernel.__new__(HelionKDAKernel) - kernel._packed_decode = MagicMock() - kernel._triton = MagicMock() - mixed_qkv = torch.empty(2, 16) - a = torch.empty(2, 8) - b = torch.empty(2, 1) - a_log = torch.empty(1) - dt_bias = torch.empty(8) - state = torch.empty(2, 1, 4, 8) - indices = torch.arange(2, dtype=torch.int32) - - kernel.packed_decode( - mixed_qkv, - a, - b, - A_log=a_log, - dt_bias=dt_bias, - scale=0.5, - ssm_states=state, - cache_indices=indices, - num_v_heads=1, - head_v_dim=4, - lower_bound=-5.0, - ) - - kernel._packed_decode.assert_called_once() - self.assertEqual(kernel._packed_decode.call_args.kwargs["lower_bound"], -5.0) - def test_replayssm_accepts_helion_and_rejects_other_backends(self): with ( override_platform(is_sm100=False), diff --git a/test/registered/unit/layers/moe/test_fused_moe_triton_config.py b/test/registered/unit/layers/moe/test_fused_moe_triton_config.py index 7b35c4aac32a..f015c3d2db2b 100644 --- a/test/registered/unit/layers/moe/test_fused_moe_triton_config.py +++ b/test/registered/unit/layers/moe/test_fused_moe_triton_config.py @@ -15,37 +15,6 @@ import common_utils # noqa: E402 -def test_h200_bf16_config_is_available_for_current_triton_runtime(): - config_path = ( - Path(fused_moe_triton_config.__file__).parent - / "configs" - / "triton_3_6_0" - / "E=128,N=768,device_name=NVIDIA_H200.json" - ) - - assert config_path.is_file() - assert json.loads(config_path.read_text())["128"]["BLOCK_SIZE_M"] > 0 - - -def test_h100_lingbot_video_configs_enable_tma_only_for_the_tuned_shape(): - config_root = ( - Path(fused_moe_triton_config.__file__).parent / "configs" / "triton_3_7_1" - ) - - for suffix in ("", "_down"): - config_path = ( - config_root / f"E=128,N=768,device_name=NVIDIA_H100_80GB_HBM3{suffix}.json" - ) - configs = json.loads(config_path.read_text()) - - assert configs["4096"]["USE_TMA"] is True - assert all( - "USE_TMA" not in config - for num_tokens, config in configs.items() - if num_tokens != "4096" - ) - - def test_down_moe_reuses_tuned_up_config_when_separate_config_is_absent( monkeypatch, tmp_path ): diff --git a/test/registered/unit/layers/moe/test_mega_moe_deepgemm_api.py b/test/registered/unit/layers/moe/test_mega_moe_deepgemm_api.py index 445d567accf9..66b219e5d6fa 100644 --- a/test/registered/unit/layers/moe/test_mega_moe_deepgemm_api.py +++ b/test/registered/unit/layers/moe/test_mega_moe_deepgemm_api.py @@ -68,15 +68,6 @@ def test_mxf4_buffer_uses_typed_api(self): self.assertEqual(call.kwargs.get("mma_type"), "mxf4xmxf4") self.assertNotIn("use_fp8_dispatch", call.kwargs) - def test_server_flag_selects_mxf4_mma_type(self): - for enabled, expected in ((False, "fp8xfp4"), (True, "mxf4xmxf4")): - with self.subTest(enabled=enabled): - config = SimpleNamespace( - moe=SimpleNamespace(enable_w4a4_mxfp4_megamoe=enabled) - ) - with patch.object(mega_moe, "get_exec", return_value=config): - self.assertEqual(mega_moe._mega_moe_mma_type(), expected) - def test_buffer_cache_separates_mma_types(self): deep_gemm = self.deep_gemm expected_buffers = (object(), object()) diff --git a/test/registered/unit/layers/quantization/test_bf16_splitk_gemm.py b/test/registered/unit/layers/quantization/test_bf16_splitk_gemm.py index 5e663cc0db1a..be3dc332440f 100644 --- a/test/registered/unit/layers/quantization/test_bf16_splitk_gemm.py +++ b/test/registered/unit/layers/quantization/test_bf16_splitk_gemm.py @@ -30,12 +30,6 @@ def test_splitk_rejects_unmeasured_shapes(shape: tuple[int, int, int]): assert not use_bf16_splitk_gemm(*shape) -def test_bf16_splitk_is_enabled_by_default(): - assert envs.SGLANG_ENABLE_BF16_SPLITK_GEMM.default is True - with envs.SGLANG_ENABLE_BF16_SPLITK_GEMM.override(True): - assert should_enable_bf16_splitk_gemm(Bf16GemmBackend.CUTEDSL) - - def test_bf16_splitk_env_kill_switch(): with envs.SGLANG_ENABLE_BF16_SPLITK_GEMM.override(False): assert not should_enable_bf16_splitk_gemm(Bf16GemmBackend.CUTEDSL) diff --git a/test/registered/unit/lora/test_laguna_hidden_dim_unit.py b/test/registered/unit/lora/test_laguna_hidden_dim_unit.py index f00bee25068e..abac77fd31d7 100644 --- a/test/registered/unit/lora/test_laguna_hidden_dim_unit.py +++ b/test/registered/unit/lora/test_laguna_hidden_dim_unit.py @@ -25,7 +25,7 @@ from sglang.srt.configs.laguna import LagunaConfig from sglang.srt.lora.utils import get_default_hidden_dim -from sglang.srt.models.laguna import LagunaForCausalLM, LagunaModel +from sglang.srt.models.laguna import LagunaModel def _make_fake_laguna(num_attention_heads_per_layer): @@ -141,22 +141,5 @@ def test_unknown_module_raises(self): self.model.get_hidden_dim("not_a_module", layer_idx=0) -class TestLagunaForCausalLMDelegation(unittest.TestCase): - """`LagunaForCausalLM.get_hidden_dim` must forward to the inner model.""" - - def test_forwards_to_inner_model(self): - inner = _make_fake_laguna([48, 64]) - causal = LagunaForCausalLM.__new__(LagunaForCausalLM) - # Bypass nn.Module.__setattr__: __new__ skips __init__, so the module - # registries it expects when assigning a Module-valued attr don't exist. - object.__setattr__(causal, "model", inner) - for module_name in ("qkv_proj", "o_proj", "gate_up_proj"): - for layer_idx in (0, 1): - self.assertEqual( - causal.get_hidden_dim(module_name, layer_idx), - inner.get_hidden_dim(module_name, layer_idx), - ) - - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/lora/test_mem_pool_ep_unit.py b/test/registered/unit/lora/test_mem_pool_ep_unit.py index 95c79478293b..7f73273bc908 100644 --- a/test/registered/unit/lora/test_mem_pool_ep_unit.py +++ b/test/registered/unit/lora/test_mem_pool_ep_unit.py @@ -378,10 +378,6 @@ def _make_fake_base_model(num_experts: int) -> torch.nn.Module: class TestNumExpertHelpers(unittest.TestCase): """`_get_num_experts` / `_get_num_local_experts` / buffer-dim picker.""" - def test_num_experts_read_from_config(self): - model = _make_fake_base_model(num_experts=8) - self.assertEqual(LoRAMemoryPool._get_num_experts(model), 8) - def test_num_local_experts_no_ep(self): pool = _make_pool( num_experts_global=8, diff --git a/test/registered/unit/managers/test_detailed_annotations.py b/test/registered/unit/managers/test_detailed_annotations.py index 604af818b74f..13dfc47843c0 100644 --- a/test/registered/unit/managers/test_detailed_annotations.py +++ b/test/registered/unit/managers/test_detailed_annotations.py @@ -4,11 +4,9 @@ span (see ``sglang.srt.utils.profile_utils.build_step_span_name``): the per-phase ``sq``/``sqsq``/``sqsk``/``sk`` terms (with the context/generation split for MIXED) are appended and are self-contained, so ``sq`` is emitted even where it -duplicates the base label's ``bs``/``toks``. This also covers the -``detailed_annotations`` plumbing on ``ProfileReq``. +duplicates the base label's ``bs``/``toks``. """ -import json import unittest from types import SimpleNamespace @@ -17,7 +15,6 @@ maybe_stub_sgl_kernel() -from sglang.srt.managers.io_struct import ProfileReq from sglang.srt.model_executor.forward_batch_info import ForwardMode from sglang.srt.model_executor.step_span_utils import ( detailed_annotations_enabled, @@ -217,18 +214,6 @@ def test_disabled_flag_is_default(self): self.assertEqual(build_step_span_name(fb), "step[EXTEND bs=1 toks=4]") -class TestDetailedAnnotationPlumbing(CustomTestCase): - def test_default_is_false(self): - self.assertFalse(ProfileReq().detailed_annotations) - - def test_json_round_trip(self): - req = ProfileReq(output_dir="/tmp/x", detailed_annotations=True) - payload = {"detailed_annotations": req.detailed_annotations} - parsed = json.loads(json.dumps(payload)) - self.assertTrue(parsed["detailed_annotations"]) - self.assertTrue(ProfileReq(**parsed).detailed_annotations) - - class TestDetailedAnnotationsToggle(CustomTestCase): """The process-wide toggle (set by the profiler manager) is the default source for build_step_span_name when no explicit flag is passed.""" diff --git a/test/registered/unit/managers/test_io_struct.py b/test/registered/unit/managers/test_io_struct.py index 5444ff5bcc60..59bb3c9283b9 100644 --- a/test/registered/unit/managers/test_io_struct.py +++ b/test/registered/unit/managers/test_io_struct.py @@ -42,7 +42,7 @@ CustomTestCase, ) -register_cuda_ci(est_time=10, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=10, stage="base-b", runner_config="1-gpu-small") register_amd_ci(est_time=8, suite="stage-b-test-1-gpu-small-amd") register_cpu_ci(est_time=6, suite="stage-b-test-cpu-intel") diff --git a/test/registered/unit/managers/test_mm_hashes.py b/test/registered/unit/managers/test_mm_hashes.py index c35dca3623f5..40423bb5f810 100644 --- a/test/registered/unit/managers/test_mm_hashes.py +++ b/test/registered/unit/managers/test_mm_hashes.py @@ -29,31 +29,6 @@ class TestMmHashesContract(CustomTestCase): - def test_generate_req_input_accepts_mm_hashes(self): - """GenerateReqInput exposes mm_hashes as an optional field.""" - req = GenerateReqInput( - text="hi", - image_data=["http://example.com/img.png"], - mm_hashes=["deadbeefcafe1234"], - ) - self.assertEqual(req.mm_hashes, ["deadbeefcafe1234"]) - - def test_generate_req_input_defaults_mm_hashes_to_none(self): - """Absent mm_hashes preserves existing (None) behavior.""" - req = GenerateReqInput(text="hi") - self.assertIsNone(req.mm_hashes) - - def test_content_hashes_are_distinct_from_feature_hashes(self): - content_hash = "sha256:" + "ab" * 32 - req = GenerateReqInput( - text="hi", - image_data=["http://example.com/img.png"], - mm_hashes=["deadbeef"], - mm_content_hashes=[content_hash], - ) - self.assertEqual(req.mm_hashes, ["deadbeef"]) - self.assertEqual(req.mm_content_hashes, [content_hash]) - def test_batched_hashes_follow_each_request(self): req = GenerateReqInput( text=["one", "two"], diff --git a/test/registered/unit/managers/test_mm_process_config.py b/test/registered/unit/managers/test_mm_process_config.py index e9c8ea3d62b8..a9c4909efc86 100644 --- a/test/registered/unit/managers/test_mm_process_config.py +++ b/test/registered/unit/managers/test_mm_process_config.py @@ -36,12 +36,6 @@ def test_empty_config_accepted(self): args = self._validate_config({}) self.assertEqual(resolution_result(args, "mm_process_config"), {}) - def test_none_config_defaults_to_empty_dict(self): - args = self._validate_config(None) - # None is kept as-is for dummy models (default happens after early return) - # but for real models it would be set to {} - self.assertIsNone(resolution_result(args, "mm_process_config")) - def test_top_level_non_dict_rejected(self): with self.assertRaises(TypeError) as ctx: self._validate_config("bad") diff --git a/test/registered/unit/managers/test_scheduler_internal_state_world_size.py b/test/registered/unit/managers/test_scheduler_internal_state_world_size.py index d5b40fecf75d..309f341ad437 100644 --- a/test/registered/unit/managers/test_scheduler_internal_state_world_size.py +++ b/test/registered/unit/managers/test_scheduler_internal_state_world_size.py @@ -92,16 +92,6 @@ def test_the_internal_state_reports_the_whole_server(self): self.assertEqual(internal_state["world_size"], 4) - def test_the_reported_size_is_not_one_replica_of_a_data_parallel_server(self): - """Each plain dp replica has its own process group, so no scheduler can report the whole server from it.""" - shape = _shape(tp_size=2, pp_size=1, dp_size=2, enable_dp_attention=False) - - internal_state = self._get_internal_state(shape) - - self.assertNotEqual( - internal_state["world_size"], shape["tp_size"] * shape["pp_size"] - ) - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/mem_cache/test_dsv4_unified_fp8_pool.py b/test/registered/unit/mem_cache/test_dsv4_unified_fp8_pool.py index 7e72aa515aa2..4857e98e3d62 100644 --- a/test/registered/unit/mem_cache/test_dsv4_unified_fp8_pool.py +++ b/test/registered/unit/mem_cache/test_dsv4_unified_fp8_pool.py @@ -1,7 +1,6 @@ import contextlib import unittest -from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import patch import torch @@ -300,113 +299,6 @@ def test_env_off_is_bf16_for_every_worker(self): ) -class TestBuildDsv4KvPoolPassesGate(CustomTestCase): - class _RecPool: - last = None - - def __init__(self, **kwargs): - type(self).last = kwargs - self._unified_kv = False - self._unified_kv_fp8 = kwargs.get("unified_fp8") - - def _kvc(self, *, is_draft_worker, spec_algorithm): - from sglang.srt.mem_cache.kv_cache_configurator import KVCacheConfigurator - - kvc = object.__new__(KVCacheConfigurator) - kvc.is_draft_worker = is_draft_worker - kvc.spec_algorithm = spec_algorithm - kvc.layer_info = SimpleNamespace( - num_effective_layers=1, start_layer=0, end_layer=1 - ) - kvc.model_config = SimpleNamespace( - compress_ratios=[0], - window_size=256, - qk_nope_head_dim=NOPE_DIM, - qk_rope_head_dim=ROPE_DIM, - index_head_dim=128, - hf_config=SimpleNamespace(kv_source_layer_ids=[]), - ) - kvc.kv_cache_dtype = torch.bfloat16 - kvc.device = "cpu" - return kvc - - def _build(self, *, is_draft_worker, spec_algorithm): - kvc = self._kvc(is_draft_worker=is_draft_worker, spec_algorithm=spec_algorithm) - sched = MagicMock() - sched.page_size = 256 - exec_cfg = MagicMock() - exec_cfg.features.enable_memory_saver = False - mem = MagicMock() - mem.enable_hisparse = False - par = MagicMock() - par.attn_dcp_size = 1 - req = SimpleNamespace(req_to_token=torch.zeros(4, 1)) - rec = self._RecPool - rec.last = None - env = "sglang.kernels.ops.attention.dsv4.unified_kv_kernels.env_gate" - with ( - patch( - "sglang.srt.mem_cache.kv_cache_configurator.DeepSeekV4TokenToKVPool", - rec, - ), - patch( - "sglang.srt.mem_cache.kv_cache_configurator.get_schedule", - return_value=sched, - ), - patch( - "sglang.srt.mem_cache.kv_cache_configurator.get_exec", - return_value=exec_cfg, - ), - patch( - "sglang.srt.mem_cache.kv_cache_configurator.get_memory", - return_value=mem, - ), - patch( - "sglang.srt.mem_cache.kv_cache_configurator.get_parallel", - return_value=par, - ), - patch( - "sglang.srt.mem_cache.kv_cache_configurator.max_speculative_num_draft_tokens", - return_value=0, - ), - patch(f"{env}.is_unified_kv_fp8", return_value=True), - ): - kvc._build_dsv4_kv_pool( - max_running_requests=2, - full_max_total_num_tokens=256, - swa_max_total_num_tokens=256, - c4_max_total_num_tokens=0, - c128_max_total_num_tokens=1, - c4_state_pool_size=0, - c128_state_pool_size=0, - c4_state_dtype=None, - c128_state_dtype=None, - req_to_token_pool=req, - ) - return rec.last - - def test_dspark_draft_ctor_gets_unified_fp8_false(self): - kw = self._build( - is_draft_worker=True, spec_algorithm=SpeculativeAlgorithm.DSPARK - ) - self.assertIsNotNone(kw) - self.assertFalse(kw["unified_fp8"]) - - def test_eagle_draft_ctor_gets_unified_fp8_true(self): - kw = self._build( - is_draft_worker=True, spec_algorithm=SpeculativeAlgorithm.EAGLE - ) - self.assertIsNotNone(kw) - self.assertTrue(kw["unified_fp8"]) - - def test_target_ctor_gets_unified_fp8_true(self): - kw = self._build( - is_draft_worker=False, spec_algorithm=SpeculativeAlgorithm.DSPARK - ) - self.assertIsNotNone(kw) - self.assertTrue(kw["unified_fp8"]) - - class TestUnifiedKvPoolFollowsCtorFp8(CustomTestCase): def _pool(self, fp8): return DeepSeekV4UnifiedKVPool( diff --git a/test/registered/unit/mem_cache/test_evict_policy.py b/test/registered/unit/mem_cache/test_evict_policy.py index 1d1fbe069d7e..b23fc02bb277 100644 --- a/test/registered/unit/mem_cache/test_evict_policy.py +++ b/test/registered/unit/mem_cache/test_evict_policy.py @@ -32,10 +32,6 @@ class TestLRUStrategy(unittest.TestCase): def setUp(self): self.strategy = LRUStrategy() - def test_priority_is_last_access_time(self): - node = _make_node(last_access_time=42.0) - self.assertEqual(self.strategy.get_priority(node), 42.0) - def test_older_access_evicted_first(self): old = _make_node(last_access_time=1.0) new = _make_node(last_access_time=10.0) @@ -48,10 +44,6 @@ class TestLFUStrategy(unittest.TestCase): def setUp(self): self.strategy = LFUStrategy() - def test_priority_is_hit_count_and_time(self): - node = _make_node(hit_count=5, last_access_time=3.0) - self.assertEqual(self.strategy.get_priority(node), (5, 3.0)) - def test_lower_hit_count_evicted_first(self): cold = _make_node(hit_count=1, last_access_time=10.0) hot = _make_node(hit_count=100, last_access_time=1.0) @@ -71,10 +63,6 @@ class TestFIFOStrategy(unittest.TestCase): def setUp(self): self.strategy = FIFOStrategy() - def test_priority_is_creation_time(self): - node = _make_node(creation_time=7.0) - self.assertEqual(self.strategy.get_priority(node), 7.0) - def test_earlier_created_evicted_first(self): first = _make_node(creation_time=1.0) second = _make_node(creation_time=5.0) @@ -87,10 +75,6 @@ class TestMRUStrategy(unittest.TestCase): def setUp(self): self.strategy = MRUStrategy() - def test_priority_is_negated_access_time(self): - node = _make_node(last_access_time=5.0) - self.assertEqual(self.strategy.get_priority(node), -5.0) - def test_most_recently_used_evicted_first(self): """MRU evicts the most recently accessed node first (lowest priority value).""" old = _make_node(last_access_time=1.0) @@ -104,10 +88,6 @@ class TestFILOStrategy(unittest.TestCase): def setUp(self): self.strategy = FILOStrategy() - def test_priority_is_negated_creation_time(self): - node = _make_node(creation_time=3.0) - self.assertEqual(self.strategy.get_priority(node), -3.0) - def test_last_created_evicted_first(self): """FILO evicts the most recently created node first.""" first = _make_node(creation_time=1.0) @@ -121,10 +101,6 @@ class TestPriorityStrategy(unittest.TestCase): def setUp(self): self.strategy = PriorityStrategy() - def test_priority_is_tuple(self): - node = _make_node(priority=2, last_access_time=4.0) - self.assertEqual(self.strategy.get_priority(node), (2, 4.0)) - def test_lower_priority_evicted_first(self): low = _make_node(priority=1, last_access_time=10.0) high = _make_node(priority=5, last_access_time=1.0) @@ -177,10 +153,6 @@ def test_custom_threshold(self): self.assertEqual(strategy.get_priority(below), (0, 1.0)) self.assertEqual(strategy.get_priority(at), (1, 1.0)) - def test_default_threshold_is_2(self): - default = SLRUStrategy() - self.assertEqual(default.protected_threshold, 2) - class TestEvictionOrdering(unittest.TestCase): """Integration-style test: sort a list of nodes by eviction priority.""" diff --git a/test/registered/unit/mem_cache/test_hicache_load_back_timing.py b/test/registered/unit/mem_cache/test_hicache_load_back_timing.py index 556ca1902538..f757190a6cc4 100644 --- a/test/registered/unit/mem_cache/test_hicache_load_back_timing.py +++ b/test/registered/unit/mem_cache/test_hicache_load_back_timing.py @@ -35,10 +35,6 @@ def _completed_pair(self, payload_floats=1024 * 1024): torch.cuda.synchronize() return start, finish - def test_elapsed_time_works(self): - start, finish = self._completed_pair() - self.assertGreater(start.elapsed_time(finish), 0.0) - def test_timing_fallback_uses_dedicated_events(self): events = [] diff --git a/test/registered/unit/mem_cache/test_mamba_path_state_cap.py b/test/registered/unit/mem_cache/test_mamba_path_state_cap.py index c22b20034da8..8b7aa1239b15 100644 --- a/test/registered/unit/mem_cache/test_mamba_path_state_cap.py +++ b/test/registered/unit/mem_cache/test_mamba_path_state_cap.py @@ -6,7 +6,6 @@ register_cpu_ci(est_time=11, suite="base-a-test-cpu") register_cuda_ci(est_time=10, stage="base-b", runner_config="1-gpu-small") -import argparse import unittest from collections import defaultdict from unittest import mock @@ -96,16 +95,6 @@ def test_server_arg_defaults_to_unlimited(self): -1, ) - def test_server_arg_cli(self): - parser = argparse.ArgumentParser() - ServerArgs.add_cli_args(parser) - - args = parser.parse_args( - ["--model-path", "dummy", "--mamba-max-states-per-path", "3"] - ) - - self.assertEqual(args.mamba_max_states_per_path, 3) - def test_server_arg_rejects_zero_and_values_below_negative_one(self): for value in (0, -2): args = ServerArgs(model_path="dummy", mamba_max_states_per_path=value) diff --git a/test/registered/unit/mem_cache/test_mem_cache_utils.py b/test/registered/unit/mem_cache/test_mem_cache_utils.py index c0f0760dc72d..7fa7c357201b 100644 --- a/test/registered/unit/mem_cache/test_mem_cache_utils.py +++ b/test/registered/unit/mem_cache/test_mem_cache_utils.py @@ -1,8 +1,6 @@ """Unit tests for mem_cache/utils.py — no server, no model loading.""" import hashlib -import sys -import types import unittest from array import array from types import SimpleNamespace @@ -200,28 +198,6 @@ def test_disabled_by_default(self, mock_env_get): self.assertIsNone(pool) self.assertIsNone(pool_type) - @patch("sglang.srt.mem_cache.utils.envs.SGLANG_MOONCAKE_CUSTOM_MEM_POOL.get") - def test_enabled_via_env(self, mock_env_get): - mock_env_get.return_value = "enabled" - mock_init = MagicMock() - mock_init.return_value = (True, "mock_pool_instance", "mooncake") - - mooncake_pkg = types.ModuleType("sglang.srt.disaggregation.mooncake") - mooncake_utils = types.ModuleType("sglang.srt.disaggregation.mooncake.utils") - mooncake_utils.init_mooncake_custom_mem_pool = mock_init - with patch.dict( - sys.modules, - { - "sglang.srt.disaggregation.mooncake": mooncake_pkg, - "sglang.srt.disaggregation.mooncake.utils": mooncake_utils, - }, - ): - enabled, pool, pool_type = maybe_init_custom_mem_pool("cuda:0") - self.assertTrue(enabled) - self.assertEqual(pool, "mock_pool_instance") - self.assertEqual(pool_type, "mooncake") - mock_init.assert_called_once_with("cuda:0") - class TestGetHashStr(unittest.TestCase): def test_hash_str_matches_pre_optimization_per_token_loop(self): diff --git a/test/registered/unit/mem_cache/test_registry.py b/test/registered/unit/mem_cache/test_registry.py index 53c1cd8e3c47..f0dab1618800 100644 --- a/test/registered/unit/mem_cache/test_registry.py +++ b/test/registered/unit/mem_cache/test_registry.py @@ -252,67 +252,6 @@ def test_unified_radix_cache_when_hierarchical(self): ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once() self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - def test_unified_radix_cache_when_hierarchical_and_hybrid_ssm(self): - ctx = _make_ctx(self, enable_hierarchical_cache=True, is_hybrid_ssm=True) - # Hybrid SSM with hierarchical cache now uses UnifiedRadixCache. - fake_components = MagicMock() - fake_radix = MagicMock() - with patch.dict( - "sys.modules", - { - "sglang.srt.mem_cache.unified_cache.components": fake_components, - "sglang.srt.mem_cache.unified_radix_cache": fake_radix, - }, - ): - result = default_radix_cache_factory(ctx) - fake_radix.UnifiedRadixCache.assert_called_once_with(ctx.params) - fake_radix.UnifiedRadixCache.return_value.init_hicache.assert_called_once_with( - ctx.server_args, ctx.params - ) - ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once() - self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - - def test_unified_radix_cache_when_hierarchical_and_hybrid_swa(self): - ctx = _make_ctx(self, enable_hierarchical_cache=True, is_hybrid_swa=True) - # Hybrid SWA with hierarchical cache also uses UnifiedRadixCache. - fake_components = MagicMock() - fake_radix = MagicMock() - with patch.dict( - "sys.modules", - { - "sglang.srt.mem_cache.unified_cache.components": fake_components, - "sglang.srt.mem_cache.unified_radix_cache": fake_radix, - }, - ): - result = default_radix_cache_factory(ctx) - fake_radix.UnifiedRadixCache.assert_called_once_with(ctx.params) - fake_radix.UnifiedRadixCache.return_value.init_hicache.assert_called_once_with( - ctx.server_args, ctx.params - ) - ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once() - self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - - def test_unified_radix_cache_when_hierarchical_and_dsa(self): - ctx = _make_ctx(self, enable_hierarchical_cache=True, is_dsa=True) - # DSA models (e.g. DeepSeek V3.2 / GLM-5.1) with hierarchical cache - # use UnifiedRadixCache. - fake_components = MagicMock() - fake_radix = MagicMock() - with patch.dict( - "sys.modules", - { - "sglang.srt.mem_cache.unified_cache.components": fake_components, - "sglang.srt.mem_cache.unified_radix_cache": fake_radix, - }, - ): - result = default_radix_cache_factory(ctx) - fake_radix.UnifiedRadixCache.assert_called_once_with(ctx.params) - fake_radix.UnifiedRadixCache.return_value.init_hicache.assert_called_once_with( - ctx.server_args, ctx.params - ) - ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once() - self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - def test_unified_radix_cache_with_mori_external_linker(self): from sglang.srt.mem_cache.storage.umbp import umbp_direct_linker @@ -364,22 +303,6 @@ def test_unified_radix_cache_with_mori_external_linker(self): ) self.assertIs(result, cache) - def test_unified_radix_cache_when_hybrid_swa(self): - ctx = _make_ctx(self, is_hybrid_swa=True) - # SWA hybrid models now default to the unified radix tree. - fake_components = MagicMock() - fake_radix = MagicMock() - with patch.dict( - "sys.modules", - { - "sglang.srt.mem_cache.unified_cache.components": fake_components, - "sglang.srt.mem_cache.unified_radix_cache": fake_radix, - }, - ): - result = default_radix_cache_factory(ctx) - fake_radix.UnifiedRadixCache.assert_called_once_with(ctx.params) - self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - def test_pure_swa_radix_cache_when_all_swa(self): ctx = _make_ctx(self, is_hybrid_swa=True, full_tokens_per_layer=0) with patch( @@ -390,22 +313,6 @@ def test_pure_swa_radix_cache_when_all_swa(self): PureSWA.assert_called_once_with(params=ctx.params) self.assertIs(result, PureSWA.return_value) - def test_unified_radix_cache_when_hybrid_ssm(self): - ctx = _make_ctx(self, is_hybrid_ssm=True) - # Mamba hybrid models now default to the unified radix tree. - fake_components = MagicMock() - fake_radix = MagicMock() - with patch.dict( - "sys.modules", - { - "sglang.srt.mem_cache.unified_cache.components": fake_components, - "sglang.srt.mem_cache.unified_radix_cache": fake_radix, - }, - ): - result = default_radix_cache_factory(ctx) - fake_radix.UnifiedRadixCache.assert_called_once_with(ctx.params) - self.assertIs(result, fake_radix.UnifiedRadixCache.return_value) - def test_lmcache_unified_radix_cache_when_enable_lmcache(self): ctx = _make_ctx(self, enable_lmcache=True) fake_module = MagicMock() diff --git a/test/registered/unit/mem_cache/test_unified_radix_cache_unittest.py b/test/registered/unit/mem_cache/test_unified_radix_cache_unittest.py index 79cdf03ca84d..f64acdecc07e 100644 --- a/test/registered/unit/mem_cache/test_unified_radix_cache_unittest.py +++ b/test/registered/unit/mem_cache/test_unified_radix_cache_unittest.py @@ -8961,33 +8961,6 @@ def test_backup_publish_node_ids_collects_component_nodes_once(self): [3, 4, 5, 7], ) - def test_apply_cache_action_routes_replace_write_through(self): - cache = mock.MagicMock() - action = ReplaceWriteThroughOnNodeSplit( - ack_id=7, old_node_id=2, new_node_id=3, new_child_node_id=2 - ) - UnifiedRadixCache._apply_cache_action(cache, action) - cache._replace_pending_write_through_node.assert_called_once_with(7, 2, [3, 2]) - - def test_apply_cache_action_routes_free_device_kv(self): - cache = mock.MagicMock() - first, second = torch.tensor([4, 5]), torch.tensor([6]) - action = FreeDeviceKV([first, second]) - UnifiedRadixCache._apply_cache_action(cache, action) - cache.token_to_kv_pool_allocator.free_segment.assert_has_calls( - [mock.call(first, start_pos=0), mock.call(second, start_pos=0)] - ) - - def test_apply_cache_action_routes_free_component_device_kv(self): - cache = mock.MagicMock() - component = mock.MagicMock() - cache.components = {ComponentType.SWA: component} - action = FreeComponentDeviceSlot( - [torch.tensor([4, 5])], component_type=ComponentType.SWA - ) - UnifiedRadixCache._apply_cache_action(cache, action) - component.apply_component_action.assert_called_once_with(action) - def test_apply_component_action_device_kv_full_swa_uses_full_attn(self): cache = mock.MagicMock() cache.is_swa_enabled = True @@ -9027,16 +9000,6 @@ def test_apply_component_action_device_kv_mamba_routes_to_int8_ckpt_pool(self): cache.req_to_token_pool.mamba_ckpt_pool.free.assert_called_once_with(indices) cache.req_to_token_pool.mamba_allocator.free.assert_not_called() - def test_apply_cache_action_routes_free_component_host_kv(self): - cache = mock.MagicMock() - component = mock.MagicMock() - cache.components = {ComponentType.SWA: component} - action = FreeComponentHostSlot( - [torch.tensor([4, 5])], component_type=ComponentType.SWA - ) - UnifiedRadixCache._apply_cache_action(cache, action) - component.apply_component_action.assert_called_once_with(action) - def test_apply_component_action_host_kv_swa(self): cache = mock.MagicMock() first, second = torch.tensor([4, 5]), torch.tensor([6]) @@ -9065,14 +9028,6 @@ def test_apply_component_action_host_kv_mamba(self): self.assertEqual(calls[0].kwargs["extra_pools"][0].name, PoolName.MAMBA) self.assertIs(calls[0].kwargs["extra_pools"][0].host_indices, indices) - def test_apply_cache_action_routes_swa_rebuild(self): - cache = mock.MagicMock() - component = mock.MagicMock() - cache.components = {ComponentType.SWA: component} - action = SWARebuild(node_id=5, source_value=torch.tensor([3, 4])) - UnifiedRadixCache._apply_cache_action(cache, action) - component.apply_component_action.assert_called_once_with(action) - def test_apply_component_action_swa_rebuild(self): cache = mock.MagicMock() alloc = cache.token_to_kv_pool_allocator @@ -9089,18 +9044,6 @@ def test_apply_component_action_swa_rebuild(self): 5, ComponentType.SWA, swa_value ) - def test_apply_cache_action_routes_swa_recover_on_full_locked(self): - cache = mock.MagicMock() - component = mock.MagicMock() - cache.components = {ComponentType.SWA: component} - action = RecoverSWAWithLockedFull( - node_id=5, - kept_full=torch.tensor([1, 2]), - incoming_full=torch.tensor([3, 4]), - ) - UnifiedRadixCache._apply_cache_action(cache, action) - component.apply_component_action.assert_called_once_with(action) - def test_apply_component_action_swa_recover_on_full_locked(self): cache = mock.MagicMock() alloc = cache.token_to_kv_pool_allocator diff --git a/test/registered/unit/mem_cache/test_unified_radix_hicache_dispatch.py b/test/registered/unit/mem_cache/test_unified_radix_hicache_dispatch.py index f132348175dc..2c27acd5dc67 100644 --- a/test/registered/unit/mem_cache/test_unified_radix_hicache_dispatch.py +++ b/test/registered/unit/mem_cache/test_unified_radix_hicache_dispatch.py @@ -1,7 +1,7 @@ import unittest from unittest.mock import MagicMock, patch -from sglang.srt.mem_cache.hicache_storage import PoolName, SidecarPoolSpec +from sglang.srt.mem_cache.hicache_storage import PoolName from sglang.srt.mem_cache.hybrid_cache import hybrid_pool_assembler from sglang.srt.mem_cache.hybrid_cache.hybrid_pool_assembler import ( _STRATEGIES, @@ -173,42 +173,6 @@ def _fake_cache(component_types): cache.components = {ct: MagicMock() for ct in component_types} return cache - def test_wires_components_sidecars_and_counters(self): - full_host, swa_host, mamba_host = MagicMock(), MagicMock(), MagicMock() - cache = self._fake_cache([FULL, SWA, MAMBA]) - kvcache = MagicMock() - params = MagicMock() - controller = MagicMock() - sidecar = SidecarPoolSpec( - pool_name=PoolName.INDEXER, indices_from_pool=PoolName.KV - ) - result = StackBuildResult( - host_pool_group=MagicMock(), - cache_controller=controller, - component_host_pools={FULL: full_host, SWA: swa_host, MAMBA: mamba_host}, - sidecars=[sidecar], - register_req_to_token_counter=True, - pools_desc="KV + SWA + MAMBA", - ) - - _apply_stack_result(cache, kvcache, params, result) - - self.assertIs(cache.host_pool_group, result.host_pool_group) - self.assertIs(cache.cache_controller, controller) - self.assertIs(cache.full_kv_pool_host, full_host) - self.assertIs(cache.swa_kv_pool_host, swa_host) - self.assertIs(cache.mamba_pool_host, mamba_host) - self.assertIs(cache.components[FULL]._full_kv_pool_host, full_host) - self.assertIs(cache.components[SWA]._swa_kv_pool_host, swa_host) - self.assertIs(cache.components[MAMBA]._mamba_pool_host, mamba_host) - cache.register_sidecar_pool.assert_called_once_with(sidecar) - kvcache.register_layer_transfer_counter.assert_called_once_with( - controller.layer_done_counter - ) - params.req_to_token_pool.register_layer_transfer_counter.assert_called_once_with( - controller.layer_done_counter - ) - def test_skips_req_to_token_counter_when_flag_false(self): cache = self._fake_cache([FULL]) kvcache = MagicMock() diff --git a/test/registered/unit/model_executor/model_runner_components/test_startup_weight_load.py b/test/registered/unit/model_executor/model_runner_components/test_startup_weight_load.py index 0c3ee44f70de..fa383ff034b9 100644 --- a/test/registered/unit/model_executor/model_runner_components/test_startup_weight_load.py +++ b/test/registered/unit/model_executor/model_runner_components/test_startup_weight_load.py @@ -674,14 +674,6 @@ def _runner(manager): runner.tp_rank = 0 return runner - def test_start_delegates_to_the_manager(self): - trace = [] - runner = self._runner(_RunnerStartupManager(trace)) - - runner.start_startup_weight_load() - - self.assertEqual(trace, ["start_prefetch"]) - def test_success_releases_ownership_after_the_barrier(self): trace = [] manager = _RunnerStartupManager(trace) diff --git a/test/registered/unit/model_executor/runner/test_decode_cuda_graph_runner.py b/test/registered/unit/model_executor/runner/test_decode_cuda_graph_runner.py index 51999cd6025b..d887956a856b 100644 --- a/test/registered/unit/model_executor/runner/test_decode_cuda_graph_runner.py +++ b/test/registered/unit/model_executor/runner/test_decode_cuda_graph_runner.py @@ -92,48 +92,6 @@ def test_primes_reversed_bs_list_and_zero_index(self): self.assertEqual(fake_self._profile_bs_list, [8, 4, 2, 1]) self.assertEqual(fake_self._profile_bs_idx, 0) - def test_profiler_built_with_trace_export_knobs(self): - with tempfile.TemporaryDirectory() as tmp: - _, mock_profile, mock_schedule, mock_record_history = self._invoke( - capture_bs=[1, 2], profiler_dir=tmp - ) - self.assertEqual(mock_profile.call_count, 1) - kwargs = mock_profile.call_args.kwargs - self.assertTrue(kwargs["record_shapes"]) - self.assertTrue(kwargs["with_stack"]) - self.assertTrue(kwargs["with_flops"]) - self.assertTrue(kwargs["profile_memory"]) - self.assertTrue(callable(kwargs["on_trace_ready"])) - # Schedule skips the two dummy/warmup runs and records the capture. - mock_schedule.assert_called_once_with(wait=2, warmup=0, active=1, repeat=0) - self.assertIs(kwargs["schedule"], mock_schedule.return_value) - # Memory history recording is armed alongside the profiler. - mock_record_history.assert_called_once() - - def test_default_dir_used_when_profiler_dir_env_unset(self): - # No SGLANG_TORCH_PROFILER_DIR -> falls back to the envs default base dir. - # Patch makedirs so the test never writes to the cwd. - fake_self = _make_fake_self([1]) - with ( - mock.patch.dict(os.environ, {_BATCH_CAPTURE: "1"}, clear=False), - mock.patch.object( - mod, "get_parallel", return_value=SimpleNamespace(tp_rank=0) - ), - mock.patch.object(mod, "profile"), - mock.patch("torch.profiler.schedule"), - mock.patch("torch.cuda.memory._record_memory_history"), - mock.patch.object(mod.os, "makedirs") as mock_makedirs, - ): - os.environ.pop("SGLANG_TORCH_PROFILER_DIR", None) - os.environ.pop(_CAPTURE_TRACE, None) - DecodeCudaGraphRunner._init_profile_context_and_memory_record(fake_self) - - mock_makedirs.assert_called_once() - self.assertEqual( - mock_makedirs.call_args.args[0], - os.path.join("/tmp", "graph_capture_profile"), - ) - class TestInitProfileOriginalMode(CustomTestCase): """No flag, original flag only, or both (precedence) -> unscheduled pass with @@ -287,16 +245,6 @@ def test_noop_when_flag_unset(self): os.path.isdir(os.path.join(tmp, "graph_capture_profile")) ) - def test_dir_helper_uses_profiler_dir(self): - with tempfile.TemporaryDirectory() as tmp: - with mock.patch.dict( - os.environ, {"SGLANG_TORCH_PROFILER_DIR": tmp}, clear=False - ): - self.assertEqual( - putils.graph_capture_profile_dir(), - os.path.join(tmp, "graph_capture_profile"), - ) - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/model_executor/runner_backend/test_full_cuda_graph_backend.py b/test/registered/unit/model_executor/runner_backend/test_full_cuda_graph_backend.py index 8b9fb595a7d0..55e79ce4fde3 100644 --- a/test/registered/unit/model_executor/runner_backend/test_full_cuda_graph_backend.py +++ b/test/registered/unit/model_executor/runner_backend/test_full_cuda_graph_backend.py @@ -163,36 +163,20 @@ def _run(self, *, size, num_tokens_per_bs, mode_name): backend = _make_backend(runner) forward_fn = mock.Mock(return_value=object()) - rf_names = [] - - def _fake_record_function(name): - rf_names.append(name) - return contextlib.nullcontext() - - with ( - mock.patch("torch.cuda.CUDAGraph", return_value="GRAPH"), - mock.patch( - "torch.profiler.record_function", side_effect=_fake_record_function - ), - ): + + with mock.patch("torch.cuda.CUDAGraph", return_value="GRAPH"): backend.capture_one(ShapeKey(size=size), forward_fn) - return profiler, forward_fn, rf_names + return profiler, forward_fn def test_steps_twice_in_warmup_and_once_after_capture(self): - profiler, forward_fn, _ = self._run( + profiler, forward_fn = self._run( size=4, num_tokens_per_bs=1, mode_name="DECODE" ) # Schedule wait=2 + active=1 => one step per warmup (x2) + one post-capture. self.assertEqual(profiler.step.call_count, 3) self.assertEqual(forward_fn.call_count, 3) - def test_capture_not_wrapped_in_record_function(self): - # The capture forward is no longer wrapped in a record_function; per-bs - # trace naming is handled by the profiler's on_trace_ready callback. - _, _, rf_names = self._run(size=4, num_tokens_per_bs=1, mode_name="DECODE") - self.assertEqual(rf_names, []) - class TestCleanup(CustomTestCase): def test_resets_graphs_before_releasing_references(self): diff --git a/test/registered/unit/model_loader/test_modelopt_loader.py b/test/registered/unit/model_loader/test_modelopt_loader.py index 86bdcce7d2ec..feccf097247c 100644 --- a/test/registered/unit/model_loader/test_modelopt_loader.py +++ b/test/registered/unit/model_loader/test_modelopt_loader.py @@ -16,12 +16,10 @@ import torch.nn as nn from transformers import PretrainedConfig -from sglang.srt.configs.device_config import DeviceConfig from sglang.srt.configs.load_config import LoadConfig from sglang.srt.configs.model_config import ModelConfig from sglang.srt.layers.linear import ReplicatedLinear from sglang.srt.layers.logits_processor import should_apply_lm_head_quant_method -from sglang.srt.layers.modelopt_utils import QUANT_CFG_CHOICES from sglang.srt.layers.moe.fused_moe_triton.layer import FusedMoE from sglang.srt.layers.quantization.fp8 import ( Fp8Config, @@ -48,17 +46,11 @@ from sglang.srt.models.muse_glimmer import MuseGlimmerForConditionalGeneration from sglang.srt.models.nano_nemotron_vl import NemotronH_Omni_Reasoning_V3 from sglang.srt.models.utils import WeightsMapper -from sglang.srt.utils import get_device from sglang.test.ci.ci_register import register_cuda_ci from sglang.test.test_utils import CustomTestCase # Note: PYTHONPATH=python should be set when running tests -# Constants for calibration parameters to avoid hard-coded values -CALIBRATION_BATCH_SIZE = 36 -CALIBRATION_NUM_SAMPLES = 512 -DEFAULT_DEVICE = "cuda:0" - register_cuda_ci(est_time=13, stage="base-b", runner_config="1-gpu-small") @@ -93,26 +85,6 @@ def setUp(self): self.mock_mp_is_initialized.start() self.model_path = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" - self.load_config = LoadConfig() - self.device_config = DeviceConfig(device=get_device()) - - # Create a basic model config with unified quantization flag - self.model_config = ModelConfig( - model_path=self.model_path, - quantization="modelopt_fp8", # Use unified quantization approach - ) - - # Also create a unified quantization config for new tests - self.unified_model_config = ModelConfig( - model_path=self.model_path, quantization="modelopt_fp8" - ) - - # Mock base model - self.mock_base_model = MagicMock(spec=nn.Module) - self.mock_base_model.eval.return_value = self.mock_base_model - self.mock_base_model.device = ( - DEFAULT_DEVICE # Add device attribute for calibration tests - ) def tearDown(self): """Clean up test fixtures.""" @@ -123,98 +95,6 @@ def tearDown(self): self.mock_get_tp_group.stop() self.mock_mp_is_initialized.stop() - @patch("sglang.srt.model_loader.loader.logger") - def test_missing_modelopt_import(self, mock_logger): - """Test error handling when modelopt library is not available.""" - - loader = ModelOptModelLoader(self.load_config) - - # Mock the base model loader method - with patch.object( - loader, "_load_modelopt_base_model", return_value=self.mock_base_model - ): - # Simulate missing modelopt by making import fail - original_import = __import__ - - def mock_import(name, *args, **kwargs): - if name.startswith("modelopt"): - raise ImportError("No module named 'modelopt'") - # Return default import behavior for other modules - return original_import(name, *args, **kwargs) - - with patch("builtins.__import__", side_effect=mock_import): - # Expect ImportError to be raised and logged - with self.assertRaises(ImportError): - loader.load_model( - model_config=self.model_config, device_config=self.device_config - ) - - # Verify error logging - mock_logger.error.assert_called_with( - "NVIDIA Model Optimizer (modelopt) library not found. " - "Please install it to use ModelOpt quantization." - ) - - @patch("sglang.srt.model_loader.loader.QUANT_CFG_CHOICES", QUANT_CFG_CHOICES) - @patch("sglang.srt.model_loader.loader.AutoTokenizer") - @patch("sglang.srt.model_loader.loader.logger") - def test_calibration_workflow_integration(self, mock_logger, mock_auto_tokenizer): - """Test end-to-end calibration workflow integration.""" - - loader = ModelOptModelLoader(self.load_config) - - # Mock tokenizer - mock_tokenizer = MagicMock() - mock_tokenizer.padding_side = "right" - mock_auto_tokenizer.from_pretrained.return_value = mock_tokenizer - - # Mock modelopt modules - mock_mtq = MagicMock() - mock_mto = MagicMock() - mock_dataset_utils = MagicMock() - - # Configure quantization config - mock_fp8_cfg = MagicMock() - mock_mtq.FP8_DEFAULT_CFG = mock_fp8_cfg - - # Configure dataset utilities - mock_calib_dataloader = MagicMock() - mock_calibrate_loop = MagicMock() - mock_dataset_utils.get_dataset_dataloader.return_value = mock_calib_dataloader - mock_dataset_utils.create_forward_loop.return_value = mock_calibrate_loop - - # Configure model as not quantized initially - mock_is_quantized = MagicMock(return_value=False) - - with patch.object( - loader, "_load_modelopt_base_model", return_value=self.mock_base_model - ): - with patch.dict( - "sys.modules", - { - "modelopt": MagicMock(), - "modelopt.torch": MagicMock(), - "modelopt.torch.opt": mock_mto, - "modelopt.torch.quantization": mock_mtq, - "modelopt.torch.quantization.utils": MagicMock( - is_quantized=mock_is_quantized - ), - "modelopt.torch.utils": MagicMock(), - "modelopt.torch.utils.dataset_utils": mock_dataset_utils, - }, - ): - # Execute the load_model method to test the full workflow - result_model = loader.load_model( - model_config=self.model_config, device_config=self.device_config - ) - - # Verify the model loading was successful - self.assertEqual(result_model, self.mock_base_model) - - # Verify key calibration components were used - # Note: We can't easily verify the exact calls due to dynamic imports, - # but we can verify the workflow completed successfully - def test_unified_quantization_flag_support(self): """Test that ModelOptModelLoader supports unified quantization flags.""" # Test modelopt_fp8 @@ -258,50 +138,6 @@ def test_quantize_and_serve_config_validation(self): self.assertIn("requires ModelOpt quantization", str(context.exception)) -class TestModelOptLoaderIntegration(CustomTestCase): - """Integration tests for ModelOptModelLoader with Engine API.""" - - @patch("sglang.srt.model_loader.loader.get_model_loader") - @patch("sglang.srt.entrypoints.engine.Engine.__init__") - def test_engine_with_modelopt_quant_cli_argument( - self, mock_engine_init, mock_get_model_loader - ): - """Test that CLI argument --modelopt-quant is properly parsed.""" - - # Mock the Engine.__init__ to avoid actual initialization - mock_engine_init.return_value = None - - # Mock get_model_loader to return our ModelOptModelLoader - mock_loader = MagicMock(spec=ModelOptModelLoader) - mock_get_model_loader.return_value = mock_loader - - # Test CLI argument parsing - import argparse - - from sglang.srt.server_args import ServerArgs - - # Create parser and add arguments - parser = argparse.ArgumentParser() - ServerArgs.add_cli_args(parser) - - # Test parsing with modelopt_quant argument - args = parser.parse_args( - [ - "--model-path", - "TinyLlama/TinyLlama-1.1B-Chat-v1.0", - "--modelopt-quant", - "fp8", - ] - ) - - # Convert to ServerArgs using the proper from_cli_args method - server_args = ServerArgs.from_cli_args(args) - - # Verify that modelopt_quant was properly parsed - self.assertEqual(server_args.modelopt_quant, "fp8") - self.assertEqual(server_args.model_path, "TinyLlama/TinyLlama-1.1B-Chat-v1.0") - - class TestParseQuantHfConfig(CustomTestCase): """Tests for _parse_quant_hf_config and _parse_modelopt_quant_config. diff --git a/test/registered/unit/models/test_nano_nemotron_vl.py b/test/registered/unit/models/test_nano_nemotron_vl.py index 5a31c353601e..34cf18cf2dee 100644 --- a/test/registered/unit/models/test_nano_nemotron_vl.py +++ b/test/registered/unit/models/test_nano_nemotron_vl.py @@ -39,31 +39,6 @@ def test_model_registry_resolves_new_architecture(self): self.assertIs(model_class, NemotronH_Omni_Reasoning_V3) self.assertEqual(architecture, "NemotronH_Omni_Reasoning_V3") - def test_exposes_language_embed_and_head(self): - model = object.__new__(NemotronH_Omni_Reasoning_V3) - nn.Module.__init__(model) - embed = object() - head = object() - model.language_model = SimpleNamespace( - get_embed_and_head=lambda: (embed, head), - lm_head=head, - ) - - self.assertEqual(model.get_embed_and_head(), (embed, head)) - self.assertIs(model.lm_head, head) - - def test_delegates_dflash_capture_to_language_model(self): - model = object.__new__(NemotronH_Omni_Reasoning_V3) - nn.Module.__init__(model) - captured_layer_ids = [] - model.language_model = SimpleNamespace( - set_dflash_layers_to_capture=captured_layer_ids.extend - ) - - model.set_dflash_layers_to_capture([1, 22, 43, 64, 85]) - - self.assertEqual(captured_layer_ids, [1, 22, 43, 64, 85]) - def test_vision_final_layernorm_is_loaded_and_applied(self): model = object.__new__(NemotronH_Omni_Reasoning_V3) nn.Module.__init__(model) diff --git a/test/registered/unit/multimodal/test_deepseek_ocr_geometry.py b/test/registered/unit/multimodal/test_deepseek_ocr_geometry.py index 6dba0e043f49..57e5c51612d8 100644 --- a/test/registered/unit/multimodal/test_deepseek_ocr_geometry.py +++ b/test/registered/unit/multimodal/test_deepseek_ocr_geometry.py @@ -25,7 +25,7 @@ from sglang.test.ci.ci_register import register_cpu_ci from sglang.test.test_utils import CustomTestCase -register_cpu_ci(est_time=60, suite="base-a-test-cpu") +register_cpu_ci(est_time=10, suite="base-a-test-cpu") def _hf_config(vision_model_name: str, projector_input_dim) -> SimpleNamespace: diff --git a/test/registered/unit/multimodal/test_gpu_feature_transport.py b/test/registered/unit/multimodal/test_gpu_feature_transport.py index b9efb7e26315..8ad893112e55 100644 --- a/test/registered/unit/multimodal/test_gpu_feature_transport.py +++ b/test/registered/unit/multimodal/test_gpu_feature_transport.py @@ -172,39 +172,6 @@ def test_cpu_transport_skips_model_opt_in_lookup(self): get_model_architecture.assert_not_called() - def test_vmm_transport_initializes_pool(self): - from sglang.srt.runtime_context import get_context - from sglang.srt.utils import cuda_vmm_transport_utils as vmm - - server_args = SimpleNamespace( - mm_feature_transport="cuda_vmm", - tokenizer_worker_num=2, - base_gpu_id=3, - tp_size=4, - nnodes=1, - ) - # The consumer count comes from the published topology. - override = get_context().override_server_args( - enable_dp_attention=False, tp_size=4, mm_feature_transport="cuda_vmm" - ) - override.install() - self.addCleanup(override.restore) - pool = object() - with ( - patch.object(vmm, "get_mm_feature_pool_size_per_worker", return_value=123), - patch.object(vmm, "CudaVmmMemoryPool", return_value=pool) as pool_class, - ): - transport = vmm.CudaVmmFeatureTransport(server_args, SimpleNamespace()) - - self.assertIs(transport.pool, pool) - pool_class.assert_called_once_with( - memory_size=123, - recycle_interval=vmm.MM_ITEM_MEMORY_POOL_RECYCLE_INTERVAL, - base_gpu_id=3, - consumer_count=4, - allow_posix_fallback=True, - ) - def test_disabled_transport_is_a_noop(self): from sglang.srt.runtime_context import get_context from sglang.srt.utils.cuda_vmm_transport_utils import ( @@ -372,31 +339,6 @@ def test_partial_failure_restores_tensors_and_cancels_packed_chunk_once(self): self.assertIs(items[0].precomputed_embeddings, embedding) pool._cancel_control_offset.assert_called_once_with(owner.control_offset) - def test_text_request_uses_base_send_path(self): - from sglang.srt.managers import tokenizer_manager - from sglang.srt.managers.tokenizer_manager import TokenizerManager - - manager = object.__new__(TokenizerManager) - manager.rid_to_state = {} - manager.encoder_dispatch_ready = {} - transport = MagicMock() - transport.prepare_for_dispatch_async = AsyncMock(return_value=[]) - manager.cuda_vmm_feature_transport = transport - manager._dispatch_to_scheduler = MagicMock() - tokenized_obj = SimpleNamespace( - rid="test-request", - mm_inputs=None, - time_stats=MagicMock(), - wrap_pickle_fields=MagicMock(), - ) - - with patch.object(tokenizer_manager, "wrap_shm_features", lambda obj: obj): - asyncio.run(manager._send_one_request(tokenized_obj)) - - manager._dispatch_to_scheduler.assert_called_once_with(tokenized_obj) - transport.prepare_for_dispatch_async.assert_awaited_once_with((None,)) - transport.cancel_for_dispatch.assert_not_called() - def test_failed_dispatch_cancels_published_items(self): from sglang.srt.managers import tokenizer_manager from sglang.srt.managers.schedule_batch import ( diff --git a/test/registered/unit/npu/attention/test_npu_ascend_backend.py b/test/registered/unit/npu/attention/test_npu_ascend_backend.py index c98aa0af314c..1917c04239b8 100644 --- a/test/registered/unit/npu/attention/test_npu_ascend_backend.py +++ b/test/registered/unit/npu/attention/test_npu_ascend_backend.py @@ -4,7 +4,6 @@ import sys import unittest -from types import SimpleNamespace from unittest.mock import MagicMock import torch @@ -30,7 +29,6 @@ from sglang.srt.hardware_backend.npu.attention.ascend_backend import ( AscendAttnBackend, AscendAttnMaskBuilder, - AscendAttnMultiStepDraftBackend, _expand_dsa_sparse_indices, _reshape_kv_for_fia_nz, ) @@ -475,78 +473,6 @@ def test_dtype_bool(self): self.assertEqual(mask.dtype, torch.bool) -class TestCanUseTnd(unittest.TestCase): - def test_128_128(self): - self.assertTrue( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=128, v_head_dim=128) - ) - ) - - def test_192_192(self): - self.assertTrue( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=192, v_head_dim=192) - ) - ) - - def test_256_256(self): - self.assertTrue( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=256, v_head_dim=256) - ) - ) - - def test_192_128(self): - self.assertTrue( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=192, v_head_dim=128) - ) - ) - - def test_64_64(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=64, v_head_dim=64) - ) - ) - - def test_128_256(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=128, v_head_dim=256) - ) - ) - - def test_256_128(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=256, v_head_dim=128) - ) - ) - - def test_128_192(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=128, v_head_dim=192) - ) - ) - - def test_192_256(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=192, v_head_dim=256) - ) - ) - - def test_96_96(self): - self.assertFalse( - AscendAttnBackend._can_use_tnd( - SimpleNamespace(qk_head_dim=96, v_head_dim=96) - ) - ) - - class TestGenerateAlibiBias(unittest.TestCase): def setUp(self): self.backend = object.__new__(AscendAttnBackend) @@ -628,79 +554,5 @@ def test_default_dtype_bfloat16(self): self.assertEqual(result.dtype, torch.bfloat16) -class TestGetVerifyBuffers(unittest.TestCase): - def test_no_verify_mask(self): - backend = object.__new__(AscendAttnBackend) - self.assertIsNone(backend.verify_mask) - - def test_update_is_noop(self): - backend = object.__new__(AscendAttnBackend) - backend.update_verify_buffers_to_fill_after_draft(None, None) - backend.update_verify_buffers_to_fill_after_draft(MagicMock(), 4) - backend.update_verify_buffers_to_fill_after_draft(None, 16) - - -class TestCommonTemplate(unittest.TestCase): - @staticmethod - def _make_draft_backend(speculative_num_steps): - backend = object.__new__(AscendAttnMultiStepDraftBackend) - backend.speculative_num_steps = speculative_num_steps - return backend - - def test_calls_fn_for_each_step(self): - """call_fn is invoked for steps 0..speculative_num_steps-2.""" - backend = self._make_draft_backend(speculative_num_steps=4) - forward_batch = MagicMock() - forward_batch.spec_info = MagicMock() - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - self.assertEqual(call_fn.call_count, 3) - for i in range(3): - call_fn.assert_any_call(i, forward_batch) - - def test_zero_steps(self): - """speculative_num_steps=1 -> no calls (range(0)).""" - backend = self._make_draft_backend(speculative_num_steps=1) - forward_batch = MagicMock() - forward_batch.spec_info = MagicMock() - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - call_fn.assert_not_called() - - def test_two_steps(self): - """speculative_num_steps=2 -> exactly one call with index 0.""" - backend = self._make_draft_backend(speculative_num_steps=2) - forward_batch = MagicMock() - forward_batch.spec_info = MagicMock() - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - call_fn.assert_called_once_with(0, forward_batch) - - def test_call_indices(self): - backend = self._make_draft_backend(speculative_num_steps=5) - forward_batch = MagicMock() - forward_batch.spec_info = MagicMock() - indices = [] - backend.common_template(forward_batch, lambda i, fb: indices.append(i)) - self.assertEqual(indices, [0, 1, 2, 3]) - - def test_assert_spec_info_not_none(self): - """Raises AssertionError when forward_batch.spec_info is None.""" - backend = self._make_draft_backend(speculative_num_steps=4) - forward_batch = MagicMock() - forward_batch.spec_info = None - with self.assertRaises(AssertionError): - backend.common_template(forward_batch, MagicMock()) - - def test_passes_same_forward_batch(self): - backend = self._make_draft_backend(speculative_num_steps=3) - forward_batch = MagicMock() - forward_batch.spec_info = MagicMock() - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - for call in call_fn.call_args_list: - self.assertIs(call.args[1], forward_batch) - - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/npu/attention/test_npu_ascend_dsv4_backend.py b/test/registered/unit/npu/attention/test_npu_ascend_dsv4_backend.py index 3fc7e24359cd..769ee8a491a6 100644 --- a/test/registered/unit/npu/attention/test_npu_ascend_dsv4_backend.py +++ b/test/registered/unit/npu/attention/test_npu_ascend_dsv4_backend.py @@ -964,55 +964,6 @@ def test_normal_case_returns_tensor(self): self.assertIsInstance(result, torch.Tensor) -class TestCommonTemplate(unittest.TestCase): - def _make_backend(self, speculative_num_steps): - backend = object.__new__(DeepseekV4AscendMultiStepDraftBackend) - backend.speculative_num_steps = speculative_num_steps - return backend - - def test_calls_call_fn_for_each_step(self): - backend = self._make_backend(speculative_num_steps=4) - forward_batch = SimpleNamespace(spec_info=object()) - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - # range(speculative_num_steps - 1) = range(3) -> i=0,1,2 - self.assertEqual(call_fn.call_count, 3) - for i, call in enumerate(call_fn.call_args_list): - self.assertEqual(call.args[0], i) - self.assertIs(call.args[1], forward_batch) - - def test_single_step_no_calls(self): - backend = self._make_backend(speculative_num_steps=1) - forward_batch = SimpleNamespace(spec_info=object()) - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - self.assertEqual(call_fn.call_count, 0) - - def test_two_steps_one_call(self): - backend = self._make_backend(speculative_num_steps=2) - forward_batch = SimpleNamespace(spec_info=object()) - call_fn = MagicMock() - backend.common_template(forward_batch, call_fn) - self.assertEqual(call_fn.call_count, 1) - self.assertEqual(call_fn.call_args_list[0].args[0], 0) - - def test_asserts_spec_info_not_none(self): - backend = self._make_backend(speculative_num_steps=3) - forward_batch = SimpleNamespace(spec_info=None) - call_fn = MagicMock() - with self.assertRaises(AssertionError): - backend.common_template(forward_batch, call_fn) - self.assertEqual(call_fn.call_count, 0) - - def test_call_fn_exception_propagates(self): - backend = self._make_backend(speculative_num_steps=3) - forward_batch = SimpleNamespace(spec_info=object()) - call_fn = MagicMock(side_effect=RuntimeError("boom")) - with self.assertRaises(RuntimeError): - backend.common_template(forward_batch, call_fn) - self.assertEqual(call_fn.call_count, 1) - - class TestCompressorEpilogEmptyWrite(unittest.TestCase): @staticmethod def _backend(*, loc, graph_mode=False): diff --git a/test/registered/unit/npu/attention/test_npu_mla_preprocess.py b/test/registered/unit/npu/attention/test_npu_mla_preprocess.py index 338b6bc41573..74c3a6558913 100644 --- a/test/registered/unit/npu/attention/test_npu_mla_preprocess.py +++ b/test/registered/unit/npu/attention/test_npu_mla_preprocess.py @@ -148,31 +148,6 @@ def test_3d_weight(self): self.assertTrue(torch.equal(result[e, 4:8], expected_rope)) -class TestIsMlaPreprocessEnabled(unittest.TestCase): - def setUp(self): - is_mla_preprocess_enabled.cache_clear() - - def tearDown(self): - is_mla_preprocess_enabled.cache_clear() - - def test_not_set_returns_false(self): - with patch.dict(os.environ): - os.environ.pop("SGLANG_NPU_USE_MLAPO", None) - self.assertFalse(is_mla_preprocess_enabled()) - - def test_set_to_one_returns_true(self): - with patch.dict(os.environ, {"SGLANG_NPU_USE_MLAPO": "1"}): - self.assertTrue(is_mla_preprocess_enabled()) - - def test_set_to_zero_returns_false(self): - with patch.dict(os.environ, {"SGLANG_NPU_USE_MLAPO": "0"}): - self.assertFalse(is_mla_preprocess_enabled()) - - def test_set_to_true_returns_true(self): - with patch.dict(os.environ, {"SGLANG_NPU_USE_MLAPO": "true"}): - self.assertTrue(is_mla_preprocess_enabled()) - - class TestIsFiaNz(unittest.TestCase): def setUp(self): is_mla_preprocess_enabled.cache_clear() diff --git a/test/registered/unit/observability/test_func_timer.py b/test/registered/unit/observability/test_func_timer.py index 6f646928cbb2..a5855546cc6e 100644 --- a/test/registered/unit/observability/test_func_timer.py +++ b/test/registered/unit/observability/test_func_timer.py @@ -7,10 +7,10 @@ import asyncio import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import sglang.srt.observability.func_timer as func_timer -from sglang.srt.observability.func_timer import enable_func_timer, time_func_latency +from sglang.srt.observability.func_timer import time_func_latency class TestFuncTimer(unittest.TestCase): @@ -22,14 +22,6 @@ def tearDown(self): func_timer.enable_metrics = self.orig_enable func_timer.FUNC_LATENCY = self.orig_latency - @patch("prometheus_client.Histogram") - def test_enable_func_timer(self, MockHistogram): - """Sets enable_metrics and creates FUNC_LATENCY histogram.""" - enable_func_timer() - self.assertTrue(func_timer.enable_metrics) - self.assertIs(func_timer.FUNC_LATENCY, MockHistogram.return_value) - MockHistogram.assert_called_once() - def test_sync_disabled(self): """Sync function passes through when metrics disabled.""" func_timer.enable_metrics = False diff --git a/test/registered/unit/observability/test_request_metrics_exporter.py b/test/registered/unit/observability/test_request_metrics_exporter.py index 32f407c90893..d93f8c131d54 100644 --- a/test/registered/unit/observability/test_request_metrics_exporter.py +++ b/test/registered/unit/observability/test_request_metrics_exporter.py @@ -286,16 +286,6 @@ def test_write_record_skips_health_check(self): files = os.listdir(self.tmp_dir) self.assertEqual(len(files), 0) - def test_write_record_handler_none(self): - """If file handler is None after ensure, write_record returns early.""" - exporter = self._make_exporter() - obj = _GenerateReqInput(rid="req-1") - - with patch.object(exporter, "_ensure_file_handler"): - exporter._current_file_handler = None - asyncio.run(exporter.write_record(obj, {})) - # No crash, no file written - def test_write_record_exception(self): """Exceptions during write are caught and logged.""" exporter = self._make_exporter() diff --git a/test/registered/unit/observability/test_startup_func_log_and_timer.py b/test/registered/unit/observability/test_startup_func_log_and_timer.py index e75497daf474..bda9169a04a4 100644 --- a/test/registered/unit/observability/test_startup_func_log_and_timer.py +++ b/test/registered/unit/observability/test_startup_func_log_and_timer.py @@ -10,7 +10,6 @@ import sglang.srt.observability.startup_func_log_and_timer as mod from sglang.srt.observability.startup_func_log_and_timer import ( - enable_startup_timer, get_max_duration, reset_startup_timers, set_startup_metric, @@ -30,13 +29,6 @@ def tearDown(self): mod.STARTUP_LATENCY_SECONDS = self.orig_gauge mod._max_durations.clear() - @patch("prometheus_client.Gauge") - def test_enable_startup_timer(self, MockGauge): - enable_startup_timer() - self.assertTrue(mod.enable_startup_metrics) - self.assertIs(mod.STARTUP_LATENCY_SECONDS, MockGauge.return_value) - MockGauge.assert_called_once() - def test_reset_and_get_max_duration(self): mod._max_durations["ctx"] = 5.0 self.assertAlmostEqual(get_max_duration("ctx"), 5.0) diff --git a/test/registered/unit/observability/test_stat_loggers_di.py b/test/registered/unit/observability/test_stat_loggers_di.py index 9eb551fbcdc7..0d3883f1414a 100644 --- a/test/registered/unit/observability/test_stat_loggers_di.py +++ b/test/registered/unit/observability/test_stat_loggers_di.py @@ -3,9 +3,6 @@ These tests cover the small, in-process pieces of the ``stat_loggers`` dependency injection feature: -* The four DI hook class attributes (``_counter_cls``/``_gauge_cls``/ - ``_histogram_cls``/``_summary_cls``) default to ``None`` on every - collector, so the existing prometheus_client backend is used unchanged. * ``resolve_collector_class()`` returns the registered subclass when a role is present in ``stat_loggers`` and falls back to the default otherwise. * Without any subclass override, collectors instantiate the real @@ -33,7 +30,6 @@ STAT_LOGGER_ROLE_SCHEDULER, STAT_LOGGER_ROLE_STORAGE, STAT_LOGGER_ROLE_TOKENIZER, - ExpertDispatchCollector, RadixCacheMetricsCollector, SchedulerMetricsCollector, StorageMetricsCollector, @@ -86,32 +82,6 @@ class _RecordingStorageMetricsCollector(StorageMetricsCollector): _histogram_cls = _RecordingMetric -class TestCollectorClassAttrs(unittest.TestCase): - """All five collectors expose four DI hook class attrs, all defaulting to - None so the existing prometheus_client backend is used unchanged.""" - - def test_scheduler_collector_attrs_default_none(self): - self.assertIsNone(SchedulerMetricsCollector._counter_cls) - self.assertIsNone(SchedulerMetricsCollector._gauge_cls) - self.assertIsNone(SchedulerMetricsCollector._histogram_cls) - self.assertIsNone(SchedulerMetricsCollector._summary_cls) - - def test_tokenizer_collector_attrs_default_none(self): - self.assertIsNone(TokenizerMetricsCollector._counter_cls) - self.assertIsNone(TokenizerMetricsCollector._histogram_cls) - - def test_storage_collector_attrs_default_none(self): - self.assertIsNone(StorageMetricsCollector._counter_cls) - self.assertIsNone(StorageMetricsCollector._histogram_cls) - - def test_expert_dispatch_collector_attrs_default_none(self): - self.assertIsNone(ExpertDispatchCollector._histogram_cls) - - def test_radix_cache_collector_attrs_default_none(self): - self.assertIsNone(RadixCacheMetricsCollector._counter_cls) - self.assertIsNone(RadixCacheMetricsCollector._histogram_cls) - - class TestResolveCollectorClass(unittest.TestCase): """The role table is read from the published `observability` bag.""" diff --git a/test/registered/unit/observability/test_trace.py b/test/registered/unit/observability/test_trace.py index 3c4cfffa17cf..924a814b6fc7 100644 --- a/test/registered/unit/observability/test_trace.py +++ b/test/registered/unit/observability/test_trace.py @@ -20,7 +20,6 @@ TraceThreadInfo, extract_trace_headers, get_global_trace_level, - get_global_tracing_enabled, process_tracing_init, set_global_trace_level, trace_set_thread_info, @@ -74,14 +73,6 @@ def test_global_trace_level_env_var(self): finally: get_resources().trace_level = orig - def test_get_global_tracing_enabled(self): - self.assertEqual(get_global_tracing_enabled(), mod.opentelemetry_initialized) - - def test_get_cur_time_ns(self): - ts = mod.get_cur_time_ns() - self.assertIsInstance(ts, int) - self.assertGreater(ts, 0) - class TestTraceNullContext(unittest.TestCase): def test_null_object_pattern(self): diff --git a/test/registered/unit/platforms/test_platform_interface.py b/test/registered/unit/platforms/test_platform_interface.py index 1e36b9b43759..163bb6cc33f6 100644 --- a/test/registered/unit/platforms/test_platform_interface.py +++ b/test/registered/unit/platforms/test_platform_interface.py @@ -61,40 +61,6 @@ def _make_platform_ep(name, load_fn=None): return ep -# --------------------------------------------------------------------------- -# PlatformEnum & CpuArchEnum -# --------------------------------------------------------------------------- - - -class TestPlatformEnum(CustomTestCase): - """Tests for PlatformEnum enumeration.""" - - def test_all_expected_values_exist(self): - expected = { - "CUDA", - "ROCM", - "CPU", - "XPU", - "MUSA", - "NPU", - "TPU", - "MPS", - "OOT", - "UNSPECIFIED", - } - actual = {member.name for member in PlatformEnum} - self.assertEqual(actual, expected) - - -class TestCpuArchEnum(CustomTestCase): - """Tests for CpuArchEnum enumeration.""" - - def test_all_expected_values_exist(self): - expected = {"X86", "ARM", "UNSPECIFIED"} - actual = {member.name for member in CpuArchEnum} - self.assertEqual(actual, expected) - - # --------------------------------------------------------------------------- # DeviceCapability # --------------------------------------------------------------------------- @@ -227,12 +193,6 @@ def test_default_get_device_returns_cuda_device(self): base = CudaSRTPlatform() self.assertEqual(base.get_device(2), torch.device("cuda", 2)) - @patch("torch.cuda.get_device_capability", return_value=(9, 0)) - def test_default_get_device_capability_uses_cuda(self, mock_get_device_capability): - base = CudaSRTPlatform() - self.assertEqual(base.get_device_capability(1), DeviceCapability(9, 0)) - mock_get_device_capability.assert_called_once_with(1) - def test_pin_memory_available_for_cuda_targets(self): base = CudaSRTPlatform() self.assertTrue(base.is_pin_memory_available()) @@ -259,12 +219,6 @@ def test_default_seed_everything_seeds_cuda( mock_torch_seed.assert_called_once_with(123) mock_cuda_seed.assert_called_once_with(123) - def test_cuda_srt_platform_capabilities(self): - base = CudaSRTPlatform() - self.assertTrue(base.supports_fp8()) - self.assertTrue(base.support_cuda_graph()) - self.assertTrue(base.support_piecewise_cuda_graph()) - class TestXpuDeviceMixin(CustomTestCase): """Tests for XPU device operation defaults.""" @@ -273,24 +227,6 @@ def test_default_get_device_returns_xpu_device(self): base = XpuSRTPlatform() self.assertEqual(base.get_device(2), torch.device("xpu", 2)) - # TODO: @patch("torch.xpu.get_device_capability", return_value=(9, 0)) - def test_default_get_device_capability_uses_xpu(self): - # torch.ops.sgl_kernel.query_device is only registered by XPU builds - # of sgl-kernel, so patch the op namespace attribute with create=True - # (a dotted @patch target would fail to import on CPU/CUDA machines). - # torch.xpu.current_device() likewise needs an XPU device; mock it. - base = XpuSRTPlatform() - fake_query_device = MagicMock() - fake_query_device.default.return_value = (9, 0) - with ( - patch("torch.xpu.current_device", return_value=0), - patch.object( - torch.ops.sgl_kernel, "query_device", fake_query_device, create=True - ), - ): - self.assertEqual(base.get_device_capability(0), DeviceCapability(9, 0)) - fake_query_device.default.assert_called_once_with(0) - def test_pin_memory_available_for_xpu_targets(self): base = XpuSRTPlatform() self.assertTrue(base.is_pin_memory_available()) @@ -311,12 +247,6 @@ def test_default_seed_everything_seeds_xpu( mock_torch_seed.assert_called_once_with(123) mock_xpu_seed.assert_called_once_with(123) - def test_xpu_srt_platform_capabilities(self): - base = XpuSRTPlatform() - self.assertFalse(base.supports_fp8()) - self.assertTrue(base.support_cuda_graph()) - self.assertTrue(base.support_piecewise_cuda_graph()) - class TestNpuDeviceMixin(CustomTestCase): """Tests for NPU device operation defaults.""" @@ -349,46 +279,6 @@ def test_default_get_device_capability_reports_zero(self): self.assertEqual(base.get_device_capability(1), DeviceCapability(0, 0)) mock_npu.get_device_capability.assert_not_called() - def test_memory_queries_delegate_to_torch_npu(self): - base = NPUSRTPlatform() - mock_npu = MagicMock() - mock_npu.get_device_properties.return_value.total_memory = 32 * 1024**3 - mock_npu.max_memory_allocated.return_value = 5 * 10**8 - mock_npu.mem_get_info.return_value = (10**9, 2 * 10**9) - with patch.object(torch, "npu", mock_npu, create=True): - self.assertEqual(base.get_device_total_memory(1), 32 * 1024**3) - mock_npu.get_device_properties.assert_called_once_with(1) - self.assertEqual(base.get_current_memory_usage(), 5 * 10**8) - mock_npu.max_memory_allocated.assert_called_once_with(None) - device = torch.device("npu", 0) - base.get_current_memory_usage(device) - mock_npu.max_memory_allocated.assert_called_with(device) - self.assertEqual(base.get_available_memory(2), (10**9, 2 * 10**9)) - mock_npu.mem_get_info.assert_called_once_with(2) - - def test_device_info_queries_delegate_to_torch_npu(self): - base = NPUSRTPlatform() - mock_npu = MagicMock() - mock_npu.get_device_name.return_value = "Ascend910B4" - mock_npu.get_device_properties.return_value.uuid = "npu-uuid-0" - with patch.object(torch, "npu", mock_npu, create=True): - self.assertEqual(base.get_device_name(1), "Ascend910B4") - mock_npu.get_device_name.assert_called_once_with(1) - self.assertEqual(base.get_device_uuid(1), "npu-uuid-0") - mock_npu.get_device_properties.assert_called_once_with(1) - - def test_device_state_ops_delegate_to_torch_npu(self): - base = NPUSRTPlatform() - mock_npu = MagicMock() - with patch.object(torch, "npu", mock_npu, create=True): - device = torch.device("npu", 3) - base.set_device(device) - mock_npu.set_device.assert_called_once_with(device) - base.empty_cache() - mock_npu.empty_cache.assert_called_once() - base.synchronize() - mock_npu.synchronize.assert_called_once() - def test_pin_memory_available_for_npu_targets(self): # Pinned memory stays disabled on NPU: torch_npu's pinned-memory + # non_blocking H2D path is not verified against CANN (see @@ -428,26 +318,6 @@ def test_seed_everything_none_seed_is_noop(self): mock_torch_seed.assert_not_called() mock_npu.manual_seed_all.assert_not_called() - def test_npu_srt_platform_identity(self): - base = NPUSRTPlatform() - self.assertTrue(base.is_npu()) - self.assertFalse(base.is_cuda()) - self.assertFalse(base.is_cuda_alike()) - self.assertEqual(base.device_name, "npu") - self.assertEqual(base.device_type, "npu") - - def test_get_default_attention_backend_is_ascend(self): - self.assertEqual(NPUSRTPlatform().get_default_attention_backend(), "ascend") - - def test_get_dispatch_key_name_is_npu(self): - self.assertEqual(NPUSRTPlatform().get_dispatch_key_name(), "npu") - - def test_npu_srt_platform_capabilities(self): - base = NPUSRTPlatform() - self.assertTrue(base.supports_fp8()) - self.assertTrue(base.support_cuda_graph()) - self.assertFalse(base.support_piecewise_cuda_graph()) - class TestCpuDeviceMixin(CustomTestCase): """Tests for CPU device operation defaults (covers both x86 and ARM).""" @@ -504,15 +374,6 @@ def test_get_device_name_x86_branch(self, _mock_machine): name = base.get_device_name() self.assertIn("x86_64", name) - def test_cpu_srt_platform_capabilities(self): - base = CpuSRTPlatform() - self.assertFalse(base.supports_fp8()) - self.assertFalse(base.support_cuda_graph()) - self.assertFalse(base.support_piecewise_cuda_graph()) - # CPU has no GPU to pin host memory to. - self.assertFalse(base.is_pin_memory_available()) - self.assertFalse(base.is_pin_memory_available(device="cpu")) - class TestPinMemoryAvailability(CustomTestCase): """Tests for common pin-memory helper dispatch through platforms.""" @@ -580,34 +441,6 @@ def is_pin_memory_available(self, device=None): self.assertEqual(platform.calls, [None]) - def test_oot_platform_override_true_is_used(self): - from sglang.srt.utils import common - - class P(SRTPlatform): - _enum = PlatformEnum.OOT - device_name = "custom" - device_type = "custom" - - def is_pin_memory_available(self, device=None): - return True - - with patch.object(common, "current_platform", P()): - self.assertTrue(common.is_pin_memory_available()) - - def test_oot_platform_override_false_is_used(self): - from sglang.srt.utils import common - - class P(SRTPlatform): - _enum = PlatformEnum.OOT - device_name = "custom" - device_type = "custom" - - def is_pin_memory_available(self, device=None): - return False - - with patch.object(common, "current_platform", P()): - self.assertFalse(common.is_pin_memory_available()) - def test_oot_platform_without_override_uses_conservative_default(self): from sglang.srt.utils import common diff --git a/test/registered/unit/sampling/test_sampling_batch_info.py b/test/registered/unit/sampling/test_sampling_batch_info.py index bef594b0250a..cfcd9016d476 100644 --- a/test/registered/unit/sampling/test_sampling_batch_info.py +++ b/test/registered/unit/sampling/test_sampling_batch_info.py @@ -94,14 +94,6 @@ def test_custom_default_value(self): self.assertEqual(result[2, 0].item(), 1.0) -# SamplingBatchInfo.__len__ -class TestSamplingBatchInfoLen(CustomTestCase): - def test_len_matches_batch_size(self): - """Test that __len__ returns batch size (number of temperature rows).""" - info = _make_info(batch_size=5) - self.assertEqual(len(info), 5) - - class TestSamplingMaskBatchIndices(CustomTestCase): def test_filter_and_merge_preserve_support_logprob_modes(self): info = _make_info( diff --git a/test/registered/unit/spec/test_spec_registry.py b/test/registered/unit/spec/test_spec_registry.py index 88d10973d7ba..8cda36a6c1ff 100644 --- a/test/registered/unit/spec/test_spec_registry.py +++ b/test/registered/unit/spec/test_spec_registry.py @@ -195,21 +195,6 @@ def test_create_worker_raises_on_overlap_mismatch(self): self.algo.create_worker(server_args) -class TestValidatorHook(_RegistryIsolated): - def test_validator_invocation_is_caller_driven(self): - validator = MagicMock() - - @SpeculativeAlgorithm.register("MY_FOO", validate_server_args=validator) - def _factory(server_args): - return MagicMock - - algo = SpeculativeAlgorithm.from_string("MY_FOO") - self.assertIs(algo.validate_server_args, validator) - # Callers (e.g. ServerArgs.__post_init__) must invoke the hook themselves; - # CustomSpecAlgo does not call it from create_worker. - validator.assert_not_called() - - class TestServerArgsHook(_RegistryIsolated): def test_handle_speculative_decoding_invokes_custom_handle_server_args(self): class CustomHandleServerArgs(CustomSpecAlgo): diff --git a/test/registered/unit/test_runai_utils.py b/test/registered/unit/test_runai_utils.py index 56c50b37e933..fd431cc54981 100644 --- a/test/registered/unit/test_runai_utils.py +++ b/test/registered/unit/test_runai_utils.py @@ -45,10 +45,6 @@ def test_get_path_different_uris(self): path2 = ObjectStorageModel.get_path("s3://bucket/model-b/") self.assertNotEqual(path1, path2) - def test_get_path_contains_model_streamer(self): - path = ObjectStorageModel.get_path("s3://bucket/model/") - self.assertIn("model_streamer", path) - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/test_server_args_cli_metadata.py b/test/registered/unit/test_server_args_cli_metadata.py index 04f92850e7e6..b7a03063f8ef 100644 --- a/test/registered/unit/test_server_args_cli_metadata.py +++ b/test/registered/unit/test_server_args_cli_metadata.py @@ -3,8 +3,7 @@ import argparse import unittest -from sglang.srt.server_args import ServerArgs, _declared_default -from sglang.srt.utils.common import human_readable_int +from sglang.srt.server_args import ServerArgs from sglang.test.ci.ci_register import register_cpu_ci from sglang.test.test_utils import CustomTestCase @@ -16,64 +15,6 @@ class TestServerArgsMigratedCliMetadata(CustomTestCase): def setUpClass(cls): cls.parser = argparse.ArgumentParser() ServerArgs.add_cli_args(cls.parser) - cls.actions_by_option = { - option: action - for action in cls.parser._actions - for option in action.option_strings - } - - def test_argparse_shape_is_preserved_for_representative_migrated_options(self): - self.assertEqual( - self.actions_by_option["--dtype"].default, _declared_default("dtype") - ) - self.assertEqual( - self.actions_by_option["--dtype"].choices, - ["auto", "half", "float16", "bfloat16", "float", "float32"], - ) - self.assertIs(self.actions_by_option["--dtype"].type, str) - self.assertIs( - self.actions_by_option["--max-total-tokens"].type, human_readable_int - ) - self.assertIs( - self.actions_by_option["--max-prefill-tokens"].type, human_readable_int - ) - self.assertIs( - self.actions_by_option["--prefill-delayer-forward-passes-buckets"].type, - float, - ) - self.assertEqual( - self.actions_by_option["--prefill-delayer-forward-passes-buckets"].nargs, - "+", - ) - self.assertIs( - self.actions_by_option["--cuda-graph-prefill-max-context"].type, - human_readable_int, - ) - self.assertIsNone(self.actions_by_option["--context-bucket"].nargs) - self.assertEqual( - self.actions_by_option["--schedule-policy"].choices, - [ - "lpm", - "random", - "fcfs", - "dfs-weight", - "lof", - "priority", - "routing-key", - "hrrn", - "shortest-prefill-first", - ], - ) - self.assertEqual( - self.actions_by_option["--load-balance-method"].choices, - [ - "auto", - "round_robin", - "follow_bootstrap_room", - "total_requests", - "total_tokens", - ], - ) def test_data_parallel_aliases_keep_old_usage(self): for option in ("--data-parallel-size", "--dp-size"): diff --git a/test/registered/unit/test_server_args_migration.py b/test/registered/unit/test_server_args_migration.py index 00808302ca34..0371f11a0385 100644 --- a/test/registered/unit/test_server_args_migration.py +++ b/test/registered/unit/test_server_args_migration.py @@ -122,12 +122,6 @@ def test_literal_auto_derives_choices(self): self.assertEqual(sa.deepep_mode, "low_latency") self.assertEqual(sa.elastic_ep_backend, "none") - def test_image_processor_backend_choices(self): - for backend in ("auto", "torchvision", "pil"): - with self.subTest(backend=backend): - sa = self._parse(["--image-processor-backend", backend]) - self.assertEqual(sa.image_processor_backend, backend) - def test_startup_weight_load_mode(self): """The startup loading mode keeps serial as the safe default.""" serial = self._parse([]) diff --git a/test/registered/unit/tokenizer/test_tiktoken_tokenizer.py b/test/registered/unit/tokenizer/test_tiktoken_tokenizer.py index 115d6dd5cb1f..54ed4f63e193 100644 --- a/test/registered/unit/tokenizer/test_tiktoken_tokenizer.py +++ b/test/registered/unit/tokenizer/test_tiktoken_tokenizer.py @@ -1,7 +1,7 @@ """Unit tests for tiktoken_tokenizer — no server, no model loading.""" import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from sglang.test.ci.ci_register import register_cpu_ci from sglang.test.test_utils import CustomTestCase @@ -9,64 +9,10 @@ register_cpu_ci(est_time=11, suite="base-a-test-cpu") from sglang.srt.tokenizer.tiktoken_tokenizer import ( - CONTROL_TOKEN_TEXTS, - DEFAULT_CONTROL_TOKENS, - DEFAULT_SPECIAL_TOKENS, - EOS, - PAD, - RESERVED_TOKEN_TEXTS, - SEP, - TiktokenProcessor, TiktokenTokenizer, ) -class TestConstants(CustomTestCase): - def test_reserved_token_count(self): - self.assertEqual(len(RESERVED_TOKEN_TEXTS), 125) - - def test_reserved_token_format(self): - self.assertEqual(RESERVED_TOKEN_TEXTS[0], "<|reserved_3|>") - self.assertEqual(RESERVED_TOKEN_TEXTS[-1], "<|reserved_127|>") - - def test_control_token_count(self): - self.assertEqual(len(CONTROL_TOKEN_TEXTS), 704) - - def test_control_token_format(self): - self.assertEqual(CONTROL_TOKEN_TEXTS[0], "<|control1|>") - self.assertEqual(CONTROL_TOKEN_TEXTS[-1], "<|control704|>") - - def test_default_special_tokens_contains_all(self): - self.assertIn(PAD, DEFAULT_SPECIAL_TOKENS) - self.assertIn(EOS, DEFAULT_SPECIAL_TOKENS) - self.assertIn(SEP, DEFAULT_SPECIAL_TOKENS) - - def test_default_control_tokens_values(self): - # Note: "sep" maps to EOS and "eos" maps to SEP in the source code - self.assertEqual(DEFAULT_CONTROL_TOKENS["pad"], PAD) - self.assertEqual(DEFAULT_CONTROL_TOKENS["sep"], EOS) - self.assertEqual(DEFAULT_CONTROL_TOKENS["eos"], SEP) - - -class TestTiktokenProcessor(CustomTestCase): - def setUp(self): - tokenizer_patcher = patch( - "sglang.srt.tokenizer.tiktoken_tokenizer.TiktokenTokenizer" - ) - tokenizer_patcher.start() - self.addCleanup(tokenizer_patcher.stop) - self.processor = TiktokenProcessor(name="dummy") - - def test_image_processor_wraps_image_in_list(self): - image = "fake_image_data" - result = self.processor.image_processor(image) - self.assertEqual(result["pixel_values"], [image]) - - def test_image_processor_with_none(self): - result = self.processor.image_processor(None) - self.assertEqual(result["pixel_values"], [None]) - - class TestTiktokenTokenizer(CustomTestCase): def setUp(self): from jinja2 import Template diff --git a/test/registered/unit/tools/test_get_version_tag.py b/test/registered/unit/tools/test_get_version_tag.py index 57709fa92b5c..0198ba929d55 100644 --- a/test/registered/unit/tools/test_get_version_tag.py +++ b/test/registered/unit/tools/test_get_version_tag.py @@ -1,5 +1,4 @@ import importlib.util -import sys import unittest from pathlib import Path from unittest.mock import patch @@ -70,22 +69,6 @@ def test_pyprojects_use_describe_mode_for_setuptools_scm(self): self.assertNotIn(TAG_ONLY_DESCRIBE_COMMAND, content) self.assertIn(FALLBACK_VERSION, content) - def test_tag_only_cli_mode_remains_available_for_callers_that_need_latest_tag(self): - with ( - patch.object(sys, "argv", ["get_version_tag.py", "--tag-only"]), - patch.object( - self.version_helper, "get_latest_version_tag", return_value="v0.5.10" - ), - patch.object( - self.version_helper, "get_version_describe" - ) as version_describe, - patch("builtins.print") as print_mock, - ): - self.version_helper.main() - - version_describe.assert_not_called() - print_mock.assert_called_once_with("v0.5.10") - if __name__ == "__main__": unittest.main() diff --git a/test/registered/unit/utils/test_cpp_extension_loader.py b/test/registered/unit/utils/test_cpp_extension_loader.py index bc20abbc18e0..917b4b7193cd 100644 --- a/test/registered/unit/utils/test_cpp_extension_loader.py +++ b/test/registered/unit/utils/test_cpp_extension_loader.py @@ -40,27 +40,6 @@ def test_stale_torch_lock_is_removed_before_loading(tmp_path: Path): ) -def test_link_flags_and_cuda_toggle_reach_torch(tmp_path: Path): - build_directory = tmp_path / "test_extension" - with ( - patch( - "sglang.srt.utils.cpp_extension_loader._get_build_directory", - return_value=build_directory, - ), - patch("torch.utils.cpp_extension.load", return_value=object()) as load, - ): - load_extension_with_recovery( - "test_extension", - ["source.cpp"], - extra_ldflags=["-lcrypto"], - with_cuda=False, - ) - - kwargs = load.call_args.kwargs - assert kwargs["extra_ldflags"] == ["-lcrypto"] - assert kwargs["with_cuda"] is False - - def test_broken_extension_is_rebuilt_under_the_same_lock(tmp_path: Path): build_directory = tmp_path / "test_extension" build_directory.mkdir() diff --git a/test/registered/unit/utils/test_weight_checker.py b/test/registered/unit/utils/test_weight_checker.py index 6bd689dfa5c6..2df370879dc7 100644 --- a/test/registered/unit/utils/test_weight_checker.py +++ b/test/registered/unit/utils/test_weight_checker.py @@ -672,24 +672,6 @@ def test_passes_after_reset_then_restoring_normal_params(self): class TestHandle(_WeightCheckerTestBase): - def test_routes_to_actions(self): - with ( - patch.object(self.checker, "_snapshot") as m_snap, - patch.object(self.checker, "_reset_tensors") as m_reset, - patch.object(self.checker, "_compare") as m_compare, - patch.object( - self.checker, "_compute_checksum", return_value={"checksums": {}} - ) as m_checksum, - ): - self.checker.handle("snapshot", role="target") - self.checker.handle("reset_tensors", role="target") - self.checker.handle("compare", role="target") - self.checker.handle("checksum", role="target") - m_snap.assert_called_once() - m_reset.assert_called_once() - m_compare.assert_called_once() - m_checksum.assert_called_once() - def test_returns_none_for_non_checksum_actions(self): self.assertIsNone(self.checker.handle("snapshot", role="target")) self.assertIsNone(self.checker.handle("compare", role="target"))