[2/N] CI refactor: sperate some backend-independent CPU tasks. (#13447)

This commit is contained in:
Liangsheng Yin
2025-11-18 02:08:19 +08:00
committed by GitHub
parent ff00b6adbe
commit 6042010964
8 changed files with 69 additions and 24 deletions
+3 -1
View File
@@ -394,7 +394,9 @@ jobs:
timeout-minutes: 10
run: |
cd test/
python3 run_suite.py
python3 run_suite.py --hw cuda --suite stage-a-test-1
# temporarily put backend-independent cpu tests here
python3 run_suite.py --hw cpu --suite default
unit-test-backend-1-gpu:
needs: [check-changes, stage-a-test-1, sgl-kernel-build-wheels]
+17 -12
View File
@@ -6,6 +6,7 @@ from typing import List
class HWBackend(Enum):
CPU = auto()
CUDA = auto()
AMD = auto()
@@ -14,19 +15,24 @@ class HWBackend(Enum):
class CIRegistry:
backend: HWBackend
filename: str
estimation_time: float
stage: str
est_time: float
suite: str
def register_cuda_ci(estimation_time: float, ci_stage: str):
def register_cpu_ci(est_time: float, suite: str):
pass
def register_amd_ci(estimation_time: float, ci_stage: str):
def register_cuda_ci(est_time: float, suite: str):
pass
def register_amd_ci(est_time: float, suite: str):
pass
REGISTER_MAPPING = {
"register_cpu_ci": HWBackend.CPU,
"register_cuda_ci": HWBackend.CUDA,
"register_amd_ci": HWBackend.AMD,
}
@@ -45,28 +51,27 @@ class RegistryVisitor(ast.NodeVisitor):
return None
hw = REGISTER_MAPPING[func_call.func.id]
est_time = None
ci_stage = None
est_time, suite = None, None
for kw in func_call.keywords:
if kw.arg == "estimation_time":
if kw.arg == "est_time":
if isinstance(kw.value, ast.Constant):
est_time = kw.value.value
elif kw.arg == "ci_stage":
elif kw.arg == "suite":
if isinstance(kw.value, ast.Constant):
ci_stage = kw.value.value
suite = kw.value.value
for i, arg in enumerate(func_call.args):
if isinstance(arg, ast.Constant):
if i == 0:
est_time = arg.value
elif i == 1:
ci_stage = arg.value
suite = arg.value
assert (
est_time is not None
), "esimation_time is required and should be a constant"
assert ci_stage is not None, "ci_stage is required and should be a constant"
assert suite is not None, "suite is required and should be a constant"
return CIRegistry(
backend=hw, filename=self.filename, estimation_time=est_time, stage=ci_stage
backend=hw, filename=self.filename, est_time=est_time, suite=suite
)
def visit_Module(self, node):
@@ -12,6 +12,9 @@ from sglang.srt.function_call.llama32_detector import Llama32Detector
from sglang.srt.function_call.mistral_detector import MistralDetector
from sglang.srt.function_call.pythonic_detector import PythonicDetector
from sglang.srt.function_call.qwen3_coder_detector import Qwen3CoderDetector
from sglang.test.ci.ci_register import register_cpu_ci
register_cpu_ci(1.0, "default")
class TestPythonicDetector(unittest.TestCase):
@@ -16,6 +16,9 @@ from sglang.srt.function_call.utils import (
_get_tool_schema_defs,
get_json_schema_constraint,
)
from sglang.test.ci.ci_register import register_cpu_ci
register_cpu_ci(1.0, "default")
class TestJsonSchemaConstraint(unittest.TestCase):
@@ -1,10 +1,15 @@
import json
import logging
import pytest
from sglang.srt.entrypoints.openai.protocol import Function, Tool
from sglang.srt.environ import envs
from sglang.srt.function_call.base_format_detector import BaseFormatDetector
from sglang.srt.function_call.core_types import StreamingParseResult
from sglang.test.ci.ci_register import register_cpu_ci
register_cpu_ci(1.0, "default")
class DummyDetector(BaseFormatDetector):
@@ -17,6 +22,9 @@ class DummyDetector(BaseFormatDetector):
normal_text="", calls=self.parse_base_json(action, tools)
)
def structure_info(self):
pass
def test_unknown_tool_name_dropped_default(caplog):
"""Test that unknown tools are dropped by default (legacy behavior)."""
@@ -67,3 +75,7 @@ def test_unknown_tool_name_forwarded(caplog):
assert result.calls[0].name == "unknown_tool"
assert result.calls[0].tool_index == -1
assert json.loads(result.calls[0].parameters)["city"] == "Paris"
if __name__ == "__main__":
pytest.main([__file__])
+1 -1
View File
@@ -19,7 +19,7 @@ from sglang.test.test_programs import (
)
from sglang.test.test_utils import DEFAULT_MODEL_NAME_FOR_TEST, CustomTestCase
register_cuda_ci(estimation_time=80, ci_stage="stage-a-test-1")
register_cuda_ci(est_time=80, suite="stage-a-test-1")
class TestSRTBackend(CustomTestCase):
+30 -5
View File
@@ -1,10 +1,19 @@
import argparse
import glob
from typing import List
from sglang.test.ci.ci_register import CIRegistry, HWBackend, collect_tests
from sglang.test.ci.ci_utils import TestFile, run_unittest_files
LABEL_MAPPING = {HWBackend.CUDA: ["stage-a-test-1"]}
HW_MAPPING = {
"cpu": HWBackend.CPU,
"cuda": HWBackend.CUDA,
}
LABEL_MAPPING = {
HWBackend.CUDA: ["stage-a-test-1"],
HWBackend.CPU: ["default"],
}
def _filter_tests(
@@ -13,8 +22,8 @@ def _filter_tests(
ci_tests = [t for t in ci_tests if t.backend == hw]
ret = []
for t in ci_tests:
assert t.stage in LABEL_MAPPING[hw], f"Unknown stage {t.stage} for backend {hw}"
if t.stage == suite:
assert t.suite in LABEL_MAPPING[hw], f"Unknown stage {t.suite} for backend {hw}"
if t.suite == suite:
ret.append(t)
return ret
@@ -22,7 +31,7 @@ def _filter_tests(
def run_per_commit(hw: HWBackend, suite: str):
files = glob.glob("per_commit/**/*.py", recursive=True)
ci_tests = _filter_tests(collect_tests(files), hw, suite)
test_files = [TestFile(t.filename, t.estimation_time) for t in ci_tests]
test_files = [TestFile(t.filename, t.est_time) for t in ci_tests]
run_unittest_files(
test_files,
@@ -32,7 +41,23 @@ def run_per_commit(hw: HWBackend, suite: str):
def main():
run_per_commit(HWBackend.CUDA, "stage-a-test-1")
parser = argparse.ArgumentParser()
parser.add_argument(
"--hw",
type=str,
choices=["cpu", "cuda"],
required=True,
help="Hardware backend to run tests on.",
)
parser.add_argument(
"--suite",
type=str,
required=True,
help="Test suite to run.",
)
args = parser.parse_args()
hw = HW_MAPPING[args.hw]
run_per_commit(hw, args.suite)
if __name__ == "__main__":
-5
View File
@@ -8,7 +8,6 @@ from sglang.test.ci.ci_utils import TestFile, run_unittest_files
suites = {
"per-commit-1-gpu": [
TestFile("debug_utils/test_tensor_dump_forward_hook.py", 15),
TestFile("function_call/test_json_schema_constraint.py", 1),
TestFile("hicache/test_hicache_storage.py", 127),
TestFile("hicache/test_hicache_variants.py", 393),
TestFile("layers/attention/mamba/test_causal_conv1d.py", 25),
@@ -70,7 +69,6 @@ suites = {
TestFile("test_flashmla.py", 230),
TestFile("test_fp8_utils.py", 5),
TestFile("rotary_embedding/test_mrope.py", 10),
TestFile("test_function_call_parser.py", 10),
TestFile("test_fused_moe.py", 80),
TestFile("test_gpt_oss_1gpu.py", 750),
TestFile("test_harmony_parser.py", 20),
@@ -239,7 +237,6 @@ suites = {
TestFile("ep/test_hybrid_dp_ep_tp_mtp.py"),
TestFile("ep/test_moe_deepep.py"),
TestFile("ep/test_moe_deepep_eval_accuracy_large.py"),
TestFile("function_call/test_unknown_tool_name.py"),
TestFile("hicache/test_disaggregation_hicache.py"),
TestFile("hicache/test_hicache_storage_benchmark.py"),
TestFile("hicache/test_hicache_storage_e2e.py"),
@@ -381,7 +378,6 @@ suites = {
# NOTE: please sort the test cases alphabetically by the test file name
suite_amd = {
"per-commit-amd": [
TestFile("function_call/test_json_schema_constraint.py", 1),
# TestFile("hicache/test_hicache.py", 116), # Disabled temporarily, see https://github.com/sgl-project/sglang/issues/12575
# TestFile("hicache/test_hicache_mla.py", 127), # Disabled temporarily, # Temporarily disabled, see https://github.com/sgl-project/sglang/issues/12574
# TestFile("hicache/test_hicache_storage.py", 127), # Disabled temporarily, see https://github.com/sgl-project/sglang/issues/12575
@@ -421,7 +417,6 @@ suite_amd = {
TestFile("test_chunked_prefill.py", 410),
TestFile("test_create_kvindices.py", 2),
TestFile("test_eval_fp8_accuracy.py", 303),
TestFile("test_function_call_parser.py", 10),
TestFile("test_fused_moe.py", 30),
TestFile("test_harmony_parser.py", 20),
TestFile("test_input_embeddings.py", 38),