From a7b5f75d8842451c855b9bb8a4715bffd321607e Mon Sep 17 00:00:00 2001 From: fzyzcjy <5236035+fzyzcjy@users.noreply.github.com> Date: Sat, 17 Jan 2026 11:59:04 +0800 Subject: [PATCH] Support integration tests with Redis binary (#17045) --- .github/workflows/pr-benchmark-rust.yml | 4 +- .github/workflows/pr-test-rust.yml | 4 +- ....sh => ci_install_gateway_dependencies.sh} | 4 +- sgl-model-gateway/tests/common/mod.rs | 1 + .../tests/common/redis_test_server.rs | 118 ++++++++++++++++++ 5 files changed, 125 insertions(+), 6 deletions(-) rename scripts/ci/{ci_install_rust.sh => ci_install_gateway_dependencies.sh} (85%) create mode 100644 sgl-model-gateway/tests/common/redis_test_server.rs diff --git a/.github/workflows/pr-benchmark-rust.yml b/.github/workflows/pr-benchmark-rust.yml index 483c7954f..85f174b41 100644 --- a/.github/workflows/pr-benchmark-rust.yml +++ b/.github/workflows/pr-benchmark-rust.yml @@ -34,7 +34,7 @@ jobs: - name: Install dependencies run: | - bash scripts/ci/ci_install_rust.sh + bash scripts/ci/ci_install_gateway_dependencies.sh - name: Configure sccache uses: mozilla-actions/sccache-action@v0.0.9 @@ -117,7 +117,7 @@ jobs: - name: Install dependencies run: | - bash scripts/ci/ci_install_rust.sh + bash scripts/ci/ci_install_gateway_dependencies.sh - name: Configure sccache uses: mozilla-actions/sccache-action@v0.0.9 diff --git a/.github/workflows/pr-test-rust.yml b/.github/workflows/pr-test-rust.yml index bb3a197e5..9b707f4f7 100644 --- a/.github/workflows/pr-test-rust.yml +++ b/.github/workflows/pr-test-rust.yml @@ -33,7 +33,7 @@ jobs: - name: Install rust dependencies run: | - bash scripts/ci/ci_install_rust.sh + bash scripts/ci/ci_install_gateway_dependencies.sh - name: Configure sccache uses: mozilla-actions/sccache-action@v0.0.9 @@ -120,7 +120,7 @@ jobs: - name: Install dependencies run: | - bash scripts/ci/ci_install_rust.sh + bash scripts/ci/ci_install_gateway_dependencies.sh - name: Configure sccache uses: mozilla-actions/sccache-action@v0.0.9 diff --git a/scripts/ci/ci_install_rust.sh b/scripts/ci/ci_install_gateway_dependencies.sh similarity index 85% rename from scripts/ci/ci_install_rust.sh rename to scripts/ci/ci_install_gateway_dependencies.sh index 7f67b820c..f2a4c070e 100755 --- a/scripts/ci/ci_install_rust.sh +++ b/scripts/ci/ci_install_gateway_dependencies.sh @@ -4,10 +4,10 @@ set -euxo pipefail # Check if sudo is available if command -v sudo >/dev/null 2>&1; then sudo apt-get update - sudo apt-get install -y libssl-dev pkg-config protobuf-compiler + sudo apt-get install -y libssl-dev pkg-config protobuf-compiler redis-server else apt-get update - apt-get install -y libssl-dev pkg-config protobuf-compiler + apt-get install -y libssl-dev pkg-config protobuf-compiler redis-server fi # Install rustup (Rust installer and version manager) diff --git a/sgl-model-gateway/tests/common/mod.rs b/sgl-model-gateway/tests/common/mod.rs index 0c56c4435..4a860f3cf 100644 --- a/sgl-model-gateway/tests/common/mod.rs +++ b/sgl-model-gateway/tests/common/mod.rs @@ -4,6 +4,7 @@ pub mod mock_mcp_server; pub mod mock_openai_server; pub mod mock_worker; +pub mod redis_test_server; pub mod streaming_helpers; pub mod test_app; pub mod test_certs; diff --git a/sgl-model-gateway/tests/common/redis_test_server.rs b/sgl-model-gateway/tests/common/redis_test_server.rs new file mode 100644 index 000000000..7c5efa645 --- /dev/null +++ b/sgl-model-gateway/tests/common/redis_test_server.rs @@ -0,0 +1,118 @@ +use std::{ + process::{Child, Command}, + sync::OnceLock, + time::Duration, +}; + +use redis::RedisError; +use tracing::{info, warn}; + +static SHARED_SERVER: OnceLock = OnceLock::new(); + +pub fn get_shared_server() -> &'static RedisTestServer { + let server = SHARED_SERVER + .get_or_init(|| RedisTestServer::start().expect("Failed to start shared Redis server")); + server.wait_ready(); + server +} + +pub struct RedisTestServer { + process: Option, + port: u16, + url: String, +} + +impl RedisTestServer { + pub fn start() -> Result { + let port = portpicker::pick_unused_port() + .ok_or_else(|| "Failed to find available port".to_string())?; + let url = format!("redis://127.0.0.1:{}", port); + + let mut cmd = Command::new("redis-server"); + cmd.args([ + "--port", + &port.to_string(), + "--save", + "", + "--appendonly", + "no", + "--daemonize", + "no", + ]); + + info!("Starting redis server... cmd={cmd:?}"); + let process = cmd.spawn().map_err(|e| { + format!( + "Failed to start redis-server: {}. Is redis-server installed?", + e + ) + })?; + + Ok(Self { + process: Some(process), + port, + url, + }) + } + + pub fn wait_ready(&self) { + for _ in 0..200 { + match self.is_ready() { + Ok(()) => return, + Err(e) => info!("wait_ready failed, will retry (e={e})"), + } + std::thread::sleep(Duration::from_millis(100)); + } + panic!("Timeout waiting Redis server ready on port {}", self.port); + } + + pub fn is_ready(&self) -> Result<(), RedisError> { + let client = redis::Client::open(self.url.as_str())?; + let mut conn = client.get_connection()?; + redis::cmd("PING").query::(&mut conn)?; + info!("Redis is_ready=true url={}", self.url); + Ok(()) + } + + pub fn url(&self) -> &str { + &self.url + } +} + +impl Drop for RedisTestServer { + fn drop(&mut self) { + if let Some(mut process) = self.process.take() { + info!("Killing redis server... process={process:?}"); + if let Err(e) = process.kill() { + warn!("Failed to kill redis-server process: {}", e); + } + if let Err(e) = process.wait() { + warn!("Failed to wait for redis-server process: {}", e); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_redis_server_start_stop() { + let server = RedisTestServer::start().unwrap(); + server.wait_ready(); + assert!(server.url().starts_with("redis://")); + + let client = redis::Client::open(server.url()).unwrap(); + let mut conn = client.get_connection().unwrap(); + + let _: () = redis::cmd("SET") + .arg("test_key") + .arg("test_value") + .query(&mut conn) + .unwrap(); + + let value: String = redis::cmd("GET").arg("test_key").query(&mut conn).unwrap(); + assert_eq!(value, "test_value"); + } +}