migrate CPU-only unit tests from openai_server to unit/ (#22965)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import unittest
|
||||
|
||||
from sglang.srt.sampling.sampling_params import MAX_LEN, get_max_seq_length
|
||||
from sglang.srt.utils import kill_process_tree
|
||||
from sglang.test.ci.ci_register import register_amd_ci, register_cuda_ci
|
||||
from sglang.test.kits.matched_stop_kit import MatchedStopMixin
|
||||
@@ -32,53 +31,5 @@ class TestMatchedStop(CustomTestCase, MatchedStopMixin):
|
||||
kill_process_tree(cls.process.pid)
|
||||
|
||||
|
||||
class TestRegexPatternMaxLength(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.regex_str_to_max_len = {
|
||||
"((ab|cd(e|f){2}){3,5}g|hij)*k": MAX_LEN,
|
||||
# - '*' → infinite tokens need to be stored
|
||||
"abc*?k": MAX_LEN,
|
||||
# - '*?' → infinite tokens still need to be stored even if lazy matching used
|
||||
"^spec(foo|at)$": 7,
|
||||
# - '^' and '$' don't add any characters to the max length
|
||||
# "spec" → 4
|
||||
# "(foo|at)" → max(3, 2) = 3
|
||||
# Whole regex = 7
|
||||
"(a(bca|de(fg|hi){2,3})j){2}kl": 22,
|
||||
# - Innermost alt: "fg" vs "hi" → 2
|
||||
# - Repeat {2,3}: max = 3 * 2 = 6
|
||||
# - Inner group "de(...)": 2 (for "de") + 6 = 8.
|
||||
# - "bca" or "de(...)" → max(3, 8) = 8
|
||||
# - Whole group: "a" (1) + group (8) + "j"(1) = 10
|
||||
# - Repeat {2} → 20
|
||||
# - Add "kl"(2) → 22
|
||||
"(foo(bar|baz(qux){1,2}))|(x(yz){5,10})": 21,
|
||||
# Branch 1:
|
||||
# "foo"(3) + max("bar"(3), "baz"(3)+"qux"{2} = 3 + 6 = 9) = 3 + 9 = 12
|
||||
# Branch 2:
|
||||
# "x"(1) + "yz"{10} = 1 + 20 =21
|
||||
# Whole regex = max(12, 21) = 21
|
||||
"(((a|bc){1,3}(d(e|f){2}|gh){2,4})|(ijk|lmp(no|p){3})){5}": 90,
|
||||
# Branch A:
|
||||
# (a|bc){1,3} → max = 3 * 2 = 6
|
||||
# Inside: d(e|f){2} = 1 + 2 * 1 = 3 vs gh = 2 → max = 3
|
||||
# Repeat {2,4} → 4 * 3 = 12
|
||||
# Branch A total = 18
|
||||
# Branch B:
|
||||
# "ijk"(3) vs "lmp(no|p){3}" = 3 + 3 * max(2, 1) = 3 + 6 = 9 → max = 9
|
||||
# Branch B total = 9
|
||||
# Whole outer alt = max(18, 9) = 18
|
||||
# Repeat {5} → 90
|
||||
}
|
||||
|
||||
def test_get_max_length(self):
|
||||
for regex_str, max_len in self.regex_str_to_max_len.items():
|
||||
if max_len == MAX_LEN:
|
||||
self.assertGreaterEqual(get_max_seq_length(regex_str), MAX_LEN)
|
||||
else:
|
||||
self.assertEqual(get_max_seq_length(regex_str), max_len)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import unittest
|
||||
|
||||
from sglang.srt.sampling.sampling_params import MAX_LEN, get_max_seq_length
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
|
||||
register_cpu_ci(est_time=2, suite="stage-a-test-cpu")
|
||||
|
||||
|
||||
class TestRegexPatternMaxLength(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.regex_str_to_max_len = {
|
||||
"((ab|cd(e|f){2}){3,5}g|hij)*k": MAX_LEN,
|
||||
# - '*' -> infinite tokens need to be stored
|
||||
"abc*?k": MAX_LEN,
|
||||
# - '*?' -> infinite tokens still need to be stored even if lazy matching used
|
||||
"^spec(foo|at)$": 7,
|
||||
# - '^' and '$' don't add any characters to the max length
|
||||
# "spec" -> 4
|
||||
# "(foo|at)" -> max(3, 2) = 3
|
||||
# Whole regex = 7
|
||||
"(a(bca|de(fg|hi){2,3})j){2}kl": 22,
|
||||
# - Innermost alt: "fg" vs "hi" -> 2
|
||||
# - Repeat {2,3}: max = 3 * 2 = 6
|
||||
# - Inner group "de(...)": 2 (for "de") + 6 = 8.
|
||||
# - "bca" or "de(...)" -> max(3, 8) = 8
|
||||
# - Whole group: "a" (1) + group (8) + "j"(1) = 10
|
||||
# - Repeat {2} -> 20
|
||||
# - Add "kl"(2) -> 22
|
||||
"(foo(bar|baz(qux){1,2}))|(x(yz){5,10})": 21,
|
||||
# Branch 1:
|
||||
# "foo"(3) + max("bar"(3), "baz"(3)+"qux"{2} = 3 + 6 = 9) = 3 + 9 = 12
|
||||
# Branch 2:
|
||||
# "x"(1) + "yz"{10} = 1 + 20 =21
|
||||
# Whole regex = max(12, 21) = 21
|
||||
"(((a|bc){1,3}(d(e|f){2}|gh){2,4})|(ijk|lmp(no|p){3})){5}": 90,
|
||||
# Branch A:
|
||||
# (a|bc){1,3} -> max = 3 * 2 = 6
|
||||
# Inside: d(e|f){2} = 1 + 2 * 1 = 3 vs gh = 2 -> max = 3
|
||||
# Repeat {2,4} -> 4 * 3 = 12
|
||||
# Branch A total = 18
|
||||
# Branch B:
|
||||
# "ijk"(3) vs "lmp(no|p){3}" = 3 + 3 * max(2, 1) = 3 + 6 = 9 -> max = 9
|
||||
# Branch B total = 9
|
||||
# Whole outer alt = max(18, 9) = 18
|
||||
# Repeat {5} -> 90
|
||||
}
|
||||
|
||||
def test_get_max_length(self):
|
||||
for regex_str, max_len in self.regex_str_to_max_len.items():
|
||||
if max_len == MAX_LEN:
|
||||
self.assertGreaterEqual(get_max_seq_length(regex_str), MAX_LEN)
|
||||
else:
|
||||
self.assertEqual(get_max_seq_length(regex_str), max_len)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+2
-3
@@ -28,10 +28,9 @@ from sglang.srt.entrypoints.openai.protocol import (
|
||||
ModelList,
|
||||
UsageInfo,
|
||||
)
|
||||
from sglang.test.ci.ci_register import register_amd_ci, register_cuda_ci
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
|
||||
register_cuda_ci(est_time=2, suite="stage-b-test-1-gpu-small")
|
||||
register_amd_ci(est_time=10, suite="stage-b-test-1-gpu-small-amd")
|
||||
register_cpu_ci(est_time=2, suite="stage-a-test-cpu")
|
||||
|
||||
|
||||
class TestModelCard(unittest.TestCase):
|
||||
+26
-38
@@ -1,11 +1,15 @@
|
||||
"""
|
||||
Unit-tests for OpenAIServingChat — rewritten to use only the std-lib 'unittest'.
|
||||
Unit-tests for OpenAIServingChat -- rewritten to use only the std-lib 'unittest'.
|
||||
Run with either:
|
||||
python tests/test_serving_chat_unit.py -v
|
||||
or
|
||||
python -m unittest discover -s tests -p "test_*unit.py" -v
|
||||
"""
|
||||
|
||||
from sglang.test.test_utils import maybe_stub_sgl_kernel
|
||||
|
||||
maybe_stub_sgl_kernel() # must precede any import that pulls in sgl_kernel
|
||||
|
||||
import json
|
||||
import unittest
|
||||
import uuid
|
||||
@@ -25,10 +29,9 @@ from sglang.srt.entrypoints.openai.serving_chat import (
|
||||
)
|
||||
from sglang.srt.managers.io_struct import GenerateReqInput
|
||||
from sglang.srt.utils import get_or_create_event_loop
|
||||
from sglang.test.ci.ci_register import register_amd_ci, register_cuda_ci
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
|
||||
register_cuda_ci(est_time=8, suite="stage-b-test-1-gpu-small")
|
||||
register_amd_ci(est_time=10, suite="stage-b-test-1-gpu-small-amd")
|
||||
register_cpu_ci(est_time=8, suite="stage-a-test-cpu")
|
||||
|
||||
|
||||
class _MockTokenizerManager:
|
||||
@@ -670,45 +673,30 @@ class ServingChatTestCase(unittest.TestCase):
|
||||
def test_dpsk_v32_encoding_path(self):
|
||||
"""Test DeepSeek V3.2 encoding path detection and application."""
|
||||
from sglang.srt.managers.template_manager import TemplateManager
|
||||
from sglang.srt.server_args import PortArgs, ServerArgs
|
||||
|
||||
server_args = ServerArgs(model_path="deepseek-ai/DeepSeek-V3.2")
|
||||
port_args = PortArgs.init_new(server_args)
|
||||
# Only mock the fields that _use_dpsk_v32_encoding() actually reads:
|
||||
# tokenizer.chat_template and hf_config.architectures
|
||||
tm = _MockTokenizerManager()
|
||||
|
||||
# Use mocks for TokenizerManager components to avoid full initialization
|
||||
with patch(
|
||||
"sglang.srt.managers.tokenizer_manager.TokenizerManager"
|
||||
) as MockTokenizerManager:
|
||||
tokenizer_manager = MockTokenizerManager(server_args, port_args)
|
||||
tokenizer_manager.server_args = server_args
|
||||
tokenizer_manager.model_config = Mock()
|
||||
tokenizer_manager.model_config.get_default_sampling_params.return_value = (
|
||||
None
|
||||
)
|
||||
mock_hf_config = Mock()
|
||||
mock_hf_config.architectures = ["DeepseekV32ForCausalLM"]
|
||||
tm.model_config.hf_config = mock_hf_config
|
||||
|
||||
# Mock hf_config
|
||||
mock_hf_config = Mock()
|
||||
mock_hf_config.architectures = ["DeepseekV32ForCausalLM"]
|
||||
# Case 1: No chat template + DeepSeek V3.2 arch -> should use dpsk encoding
|
||||
tm.tokenizer.chat_template = None
|
||||
serving_chat = OpenAIServingChat(tm, TemplateManager())
|
||||
self.assertTrue(serving_chat.use_dpsk_v32_encoding)
|
||||
|
||||
tokenizer_manager.model_config.hf_config = mock_hf_config
|
||||
# Case 2: Chat template exists -> should NOT use dpsk encoding
|
||||
tm.tokenizer.chat_template = "some template"
|
||||
serving_chat = OpenAIServingChat(tm, TemplateManager())
|
||||
self.assertFalse(serving_chat.use_dpsk_v32_encoding)
|
||||
|
||||
# Case 1: No chat template in tokenizer -> should use dpsk encoding
|
||||
tokenizer_manager.tokenizer = Mock()
|
||||
tokenizer_manager.tokenizer.chat_template = None
|
||||
|
||||
serving_chat = OpenAIServingChat(tokenizer_manager, TemplateManager())
|
||||
self.assertTrue(serving_chat.use_dpsk_v32_encoding)
|
||||
|
||||
# Case 2: Chat template exists -> should NOT use dpsk encoding
|
||||
tokenizer_manager.tokenizer.chat_template = "some template"
|
||||
serving_chat = OpenAIServingChat(tokenizer_manager, TemplateManager())
|
||||
self.assertFalse(serving_chat.use_dpsk_v32_encoding)
|
||||
|
||||
# Case 3: Not DeepSeek V3.2 architecture -> should NOT use dpsk encoding
|
||||
tokenizer_manager.tokenizer.chat_template = None
|
||||
mock_hf_config.architectures = ["LlamaForCausalLM"]
|
||||
serving_chat = OpenAIServingChat(tokenizer_manager, TemplateManager())
|
||||
self.assertFalse(serving_chat.use_dpsk_v32_encoding)
|
||||
# Case 3: Not DeepSeek V3.2 architecture -> should NOT use dpsk encoding
|
||||
tm.tokenizer.chat_template = None
|
||||
mock_hf_config.architectures = ["LlamaForCausalLM"]
|
||||
serving_chat = OpenAIServingChat(tm, TemplateManager())
|
||||
self.assertFalse(serving_chat.use_dpsk_v32_encoding)
|
||||
|
||||
def test_streaming_abort_yields_error(self):
|
||||
"""Test that an abort finish reason during streaming correctly yields an error and stops."""
|
||||
+6
-3
@@ -4,6 +4,10 @@ Run with:
|
||||
python -m unittest tests.test_serving_completions_unit -v
|
||||
"""
|
||||
|
||||
from sglang.test.test_utils import maybe_stub_sgl_kernel
|
||||
|
||||
maybe_stub_sgl_kernel() # must precede any import that pulls in sgl_kernel
|
||||
|
||||
import json
|
||||
import unittest
|
||||
from http import HTTPStatus
|
||||
@@ -16,10 +20,9 @@ from sglang.srt.entrypoints.openai.protocol import CompletionRequest
|
||||
from sglang.srt.entrypoints.openai.serving_completions import OpenAIServingCompletion
|
||||
from sglang.srt.managers.tokenizer_manager import TokenizerManager
|
||||
from sglang.srt.utils import get_or_create_event_loop
|
||||
from sglang.test.ci.ci_register import register_amd_ci, register_cuda_ci
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
|
||||
register_cuda_ci(est_time=8, suite="stage-b-test-1-gpu-small")
|
||||
register_amd_ci(est_time=10, suite="stage-b-test-1-gpu-small-amd")
|
||||
register_cpu_ci(est_time=8, suite="stage-a-test-cpu")
|
||||
|
||||
|
||||
class _MockTemplateManager:
|
||||
Reference in New Issue
Block a user