[2/N] CI refactor: sperate some backend-independent CPU tasks. (#13447)
This commit is contained in:
@@ -394,7 +394,9 @@ jobs:
|
|||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
run: |
|
run: |
|
||||||
cd test/
|
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:
|
unit-test-backend-1-gpu:
|
||||||
needs: [check-changes, stage-a-test-1, sgl-kernel-build-wheels]
|
needs: [check-changes, stage-a-test-1, sgl-kernel-build-wheels]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from typing import List
|
|||||||
|
|
||||||
|
|
||||||
class HWBackend(Enum):
|
class HWBackend(Enum):
|
||||||
|
CPU = auto()
|
||||||
CUDA = auto()
|
CUDA = auto()
|
||||||
AMD = auto()
|
AMD = auto()
|
||||||
|
|
||||||
@@ -14,19 +15,24 @@ class HWBackend(Enum):
|
|||||||
class CIRegistry:
|
class CIRegistry:
|
||||||
backend: HWBackend
|
backend: HWBackend
|
||||||
filename: str
|
filename: str
|
||||||
estimation_time: float
|
est_time: float
|
||||||
stage: str
|
suite: str
|
||||||
|
|
||||||
|
|
||||||
def register_cuda_ci(estimation_time: float, ci_stage: str):
|
def register_cpu_ci(est_time: float, suite: str):
|
||||||
pass
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
REGISTER_MAPPING = {
|
REGISTER_MAPPING = {
|
||||||
|
"register_cpu_ci": HWBackend.CPU,
|
||||||
"register_cuda_ci": HWBackend.CUDA,
|
"register_cuda_ci": HWBackend.CUDA,
|
||||||
"register_amd_ci": HWBackend.AMD,
|
"register_amd_ci": HWBackend.AMD,
|
||||||
}
|
}
|
||||||
@@ -45,28 +51,27 @@ class RegistryVisitor(ast.NodeVisitor):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
hw = REGISTER_MAPPING[func_call.func.id]
|
hw = REGISTER_MAPPING[func_call.func.id]
|
||||||
est_time = None
|
est_time, suite = None, None
|
||||||
ci_stage = None
|
|
||||||
for kw in func_call.keywords:
|
for kw in func_call.keywords:
|
||||||
if kw.arg == "estimation_time":
|
if kw.arg == "est_time":
|
||||||
if isinstance(kw.value, ast.Constant):
|
if isinstance(kw.value, ast.Constant):
|
||||||
est_time = kw.value.value
|
est_time = kw.value.value
|
||||||
elif kw.arg == "ci_stage":
|
elif kw.arg == "suite":
|
||||||
if isinstance(kw.value, ast.Constant):
|
if isinstance(kw.value, ast.Constant):
|
||||||
ci_stage = kw.value.value
|
suite = kw.value.value
|
||||||
|
|
||||||
for i, arg in enumerate(func_call.args):
|
for i, arg in enumerate(func_call.args):
|
||||||
if isinstance(arg, ast.Constant):
|
if isinstance(arg, ast.Constant):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
est_time = arg.value
|
est_time = arg.value
|
||||||
elif i == 1:
|
elif i == 1:
|
||||||
ci_stage = arg.value
|
suite = arg.value
|
||||||
assert (
|
assert (
|
||||||
est_time is not None
|
est_time is not None
|
||||||
), "esimation_time is required and should be a constant"
|
), "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(
|
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):
|
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.mistral_detector import MistralDetector
|
||||||
from sglang.srt.function_call.pythonic_detector import PythonicDetector
|
from sglang.srt.function_call.pythonic_detector import PythonicDetector
|
||||||
from sglang.srt.function_call.qwen3_coder_detector import Qwen3CoderDetector
|
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):
|
class TestPythonicDetector(unittest.TestCase):
|
||||||
+3
@@ -16,6 +16,9 @@ from sglang.srt.function_call.utils import (
|
|||||||
_get_tool_schema_defs,
|
_get_tool_schema_defs,
|
||||||
get_json_schema_constraint,
|
get_json_schema_constraint,
|
||||||
)
|
)
|
||||||
|
from sglang.test.ci.ci_register import register_cpu_ci
|
||||||
|
|
||||||
|
register_cpu_ci(1.0, "default")
|
||||||
|
|
||||||
|
|
||||||
class TestJsonSchemaConstraint(unittest.TestCase):
|
class TestJsonSchemaConstraint(unittest.TestCase):
|
||||||
+12
@@ -1,10 +1,15 @@
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from sglang.srt.entrypoints.openai.protocol import Function, Tool
|
from sglang.srt.entrypoints.openai.protocol import Function, Tool
|
||||||
from sglang.srt.environ import envs
|
from sglang.srt.environ import envs
|
||||||
from sglang.srt.function_call.base_format_detector import BaseFormatDetector
|
from sglang.srt.function_call.base_format_detector import BaseFormatDetector
|
||||||
from sglang.srt.function_call.core_types import StreamingParseResult
|
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):
|
class DummyDetector(BaseFormatDetector):
|
||||||
@@ -17,6 +22,9 @@ class DummyDetector(BaseFormatDetector):
|
|||||||
normal_text="", calls=self.parse_base_json(action, tools)
|
normal_text="", calls=self.parse_base_json(action, tools)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def structure_info(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_tool_name_dropped_default(caplog):
|
def test_unknown_tool_name_dropped_default(caplog):
|
||||||
"""Test that unknown tools are dropped by default (legacy behavior)."""
|
"""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].name == "unknown_tool"
|
||||||
assert result.calls[0].tool_index == -1
|
assert result.calls[0].tool_index == -1
|
||||||
assert json.loads(result.calls[0].parameters)["city"] == "Paris"
|
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
|
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):
|
class TestSRTBackend(CustomTestCase):
|
||||||
|
|||||||
+30
-5
@@ -1,10 +1,19 @@
|
|||||||
|
import argparse
|
||||||
import glob
|
import glob
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from sglang.test.ci.ci_register import CIRegistry, HWBackend, collect_tests
|
from sglang.test.ci.ci_register import CIRegistry, HWBackend, collect_tests
|
||||||
from sglang.test.ci.ci_utils import TestFile, run_unittest_files
|
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(
|
def _filter_tests(
|
||||||
@@ -13,8 +22,8 @@ def _filter_tests(
|
|||||||
ci_tests = [t for t in ci_tests if t.backend == hw]
|
ci_tests = [t for t in ci_tests if t.backend == hw]
|
||||||
ret = []
|
ret = []
|
||||||
for t in ci_tests:
|
for t in ci_tests:
|
||||||
assert t.stage in LABEL_MAPPING[hw], f"Unknown stage {t.stage} for backend {hw}"
|
assert t.suite in LABEL_MAPPING[hw], f"Unknown stage {t.suite} for backend {hw}"
|
||||||
if t.stage == suite:
|
if t.suite == suite:
|
||||||
ret.append(t)
|
ret.append(t)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@@ -22,7 +31,7 @@ def _filter_tests(
|
|||||||
def run_per_commit(hw: HWBackend, suite: str):
|
def run_per_commit(hw: HWBackend, suite: str):
|
||||||
files = glob.glob("per_commit/**/*.py", recursive=True)
|
files = glob.glob("per_commit/**/*.py", recursive=True)
|
||||||
ci_tests = _filter_tests(collect_tests(files), hw, suite)
|
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(
|
run_unittest_files(
|
||||||
test_files,
|
test_files,
|
||||||
@@ -32,7 +41,23 @@ def run_per_commit(hw: HWBackend, suite: str):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
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__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from sglang.test.ci.ci_utils import TestFile, run_unittest_files
|
|||||||
suites = {
|
suites = {
|
||||||
"per-commit-1-gpu": [
|
"per-commit-1-gpu": [
|
||||||
TestFile("debug_utils/test_tensor_dump_forward_hook.py", 15),
|
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_storage.py", 127),
|
||||||
TestFile("hicache/test_hicache_variants.py", 393),
|
TestFile("hicache/test_hicache_variants.py", 393),
|
||||||
TestFile("layers/attention/mamba/test_causal_conv1d.py", 25),
|
TestFile("layers/attention/mamba/test_causal_conv1d.py", 25),
|
||||||
@@ -70,7 +69,6 @@ suites = {
|
|||||||
TestFile("test_flashmla.py", 230),
|
TestFile("test_flashmla.py", 230),
|
||||||
TestFile("test_fp8_utils.py", 5),
|
TestFile("test_fp8_utils.py", 5),
|
||||||
TestFile("rotary_embedding/test_mrope.py", 10),
|
TestFile("rotary_embedding/test_mrope.py", 10),
|
||||||
TestFile("test_function_call_parser.py", 10),
|
|
||||||
TestFile("test_fused_moe.py", 80),
|
TestFile("test_fused_moe.py", 80),
|
||||||
TestFile("test_gpt_oss_1gpu.py", 750),
|
TestFile("test_gpt_oss_1gpu.py", 750),
|
||||||
TestFile("test_harmony_parser.py", 20),
|
TestFile("test_harmony_parser.py", 20),
|
||||||
@@ -239,7 +237,6 @@ suites = {
|
|||||||
TestFile("ep/test_hybrid_dp_ep_tp_mtp.py"),
|
TestFile("ep/test_hybrid_dp_ep_tp_mtp.py"),
|
||||||
TestFile("ep/test_moe_deepep.py"),
|
TestFile("ep/test_moe_deepep.py"),
|
||||||
TestFile("ep/test_moe_deepep_eval_accuracy_large.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_disaggregation_hicache.py"),
|
||||||
TestFile("hicache/test_hicache_storage_benchmark.py"),
|
TestFile("hicache/test_hicache_storage_benchmark.py"),
|
||||||
TestFile("hicache/test_hicache_storage_e2e.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
|
# NOTE: please sort the test cases alphabetically by the test file name
|
||||||
suite_amd = {
|
suite_amd = {
|
||||||
"per-commit-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.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_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
|
# 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_chunked_prefill.py", 410),
|
||||||
TestFile("test_create_kvindices.py", 2),
|
TestFile("test_create_kvindices.py", 2),
|
||||||
TestFile("test_eval_fp8_accuracy.py", 303),
|
TestFile("test_eval_fp8_accuracy.py", 303),
|
||||||
TestFile("test_function_call_parser.py", 10),
|
|
||||||
TestFile("test_fused_moe.py", 30),
|
TestFile("test_fused_moe.py", 30),
|
||||||
TestFile("test_harmony_parser.py", 20),
|
TestFile("test_harmony_parser.py", 20),
|
||||||
TestFile("test_input_embeddings.py", 38),
|
TestFile("test_input_embeddings.py", 38),
|
||||||
|
|||||||
Reference in New Issue
Block a user