[2/N] CI refactor: sperate some backend-independent CPU tasks. (#13447)
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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):
|
||||
|
||||
+3
@@ -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):
|
||||
+3
@@ -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):
|
||||
+12
@@ -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__])
|
||||
@@ -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
@@ -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__":
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user