Unverified Commit 1f76fc6e authored by Byron Hsu's avatar Byron Hsu Committed by GitHub
Browse files

[router] Rust e2e test (#2184)

parent 7f076c2c
......@@ -40,8 +40,31 @@ jobs:
cd rust/
cargo test
e2e-rust:
if: github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request'
runs-on: 1-gpu-runner
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install rust dependencies
run: |
bash scripts/ci_install_rust.sh
- name: Build python binding
run: |
source "$HOME/.cargo/env"
cd rust
pip install setuptools-rust wheel build
python3 -m build
pip install dist/*.whl
- name: Run e2e test
run: |
cd rust/py_test
python3 run_suite.py
finish:
needs: [unit-test-rust]
needs: [unit-test-rust, e2e-rust]
runs-on: ubuntu-latest
steps:
- name: Finish
......
import argparse
import glob
from sglang.test.test_utils import run_unittest_files
if __name__ == "__main__":
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument(
"--timeout-per-file",
type=int,
default=1000,
help="The time limit for running one file in seconds.",
)
args = arg_parser.parse_args()
files = glob.glob("**/test_*.py", recursive=True)
exit_code = run_unittest_files(files, args.timeout_per_file)
exit(exit_code)
import multiprocessing
import time
import unittest
from types import SimpleNamespace
def terminate_process(process: multiprocessing.Process, timeout: float = 1.0) -> None:
"""Terminate a process gracefully, with forced kill as fallback.
Args:
process: The process to terminate
timeout: Seconds to wait for graceful termination before forcing kill
"""
if not process.is_alive():
return
process.terminate()
process.join(timeout=timeout)
if process.is_alive():
process.kill() # Force kill if terminate didn't work
process.join()
class TestLaunchRouter(unittest.TestCase):
def test_launch_router_no_exception(self):
# Create SimpleNamespace with default arguments
args = SimpleNamespace(
worker_urls=["http://localhost:8000"],
host="127.0.0.1",
port=30000,
policy="cache_aware",
cache_threshold=0.5,
balance_abs_threshold=32,
balance_rel_threshold=1.0001,
eviction_interval=60,
max_tree_size=2**24,
verbose=False,
)
def run_router():
try:
from sglang_router.launch_router import launch_router
router = launch_router(args)
if router is None:
return 1
return 0
except Exception as e:
print(e)
return 1
# Start router in separate process
process = multiprocessing.Process(target=run_router)
try:
process.start()
# Wait 3 seconds
time.sleep(3)
# Process is still running means router started successfully
self.assertTrue(process.is_alive())
finally:
terminate_process(process)
if __name__ == "__main__":
unittest.main()
import subprocess
import time
import unittest
from types import SimpleNamespace
import requests
from sglang.srt.utils import kill_child_process
from sglang.test.run_eval import run_eval
from sglang.test.test_utils import (
DEFAULT_MODEL_NAME_FOR_TEST,
DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
DEFAULT_URL_FOR_TEST,
)
def popen_launch_router(
model: str,
base_url: str,
dp_size: int,
timeout: float,
):
"""
Launch the router server process.
Args:
model: Model path/name
base_url: Server base URL
dp_size: Data parallel size
timeout: Server launch timeout
"""
_, host, port = base_url.split(":")
host = host[2:]
command = [
"python3",
"-m",
"sglang_router.launch_server",
"--model-path",
model,
"--host",
host,
"--port",
port,
"--dp",
str(dp_size), # Convert dp_size to string
]
# Use current environment
env = None
process = subprocess.Popen(command, stdout=None, stderr=None, env=env)
start_time = time.time()
with requests.Session() as session:
while time.time() - start_time < timeout:
try:
response = session.get(f"{base_url}/health")
if response.status_code == 200:
return process
except requests.RequestException:
pass
time.sleep(10)
raise TimeoutError("Server failed to start within the timeout period.")
class TestEvalAccuracyMini(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.model = DEFAULT_MODEL_NAME_FOR_TEST
cls.base_url = DEFAULT_URL_FOR_TEST
cls.process = popen_launch_router(
cls.model,
cls.base_url,
dp_size=1,
timeout=DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
)
@classmethod
def tearDownClass(cls):
kill_child_process(cls.process.pid, include_self=True)
def test_mmlu(self):
args = SimpleNamespace(
base_url=self.base_url,
model=self.model,
eval_name="mmlu",
num_examples=64,
num_threads=32,
temperature=0.1,
)
metrics = run_eval(args)
self.assertGreaterEqual(metrics["score"], 0.65)
if __name__ == "__main__":
unittest.main()
......@@ -656,7 +656,7 @@ mod tests {
assert_eq!(
tree.get_smallest_tenant(),
"tenant2",
"Expected tenant2 to be smallest with 3 characters"
"Expected tenant2 to be smallest with 3 characters."
);
// Insert overlapping data for tenant3 and tenant4 to test equal counts
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment