Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
- Integrate the redisclient package into the workspace. - Update the MONOREPO_CONVERSION_PLAN.md to reflect the completion of the redisclient package conversion. This includes marking its conversion as complete and updating the success metrics. - Add the redisclient package's Cargo.toml file. - Add the redisclient package's source code files. - Add tests for the redisclient package. - Add README file for the redisclient package.
385 lines
12 KiB
Rust
385 lines
12 KiB
Rust
use redis::RedisResult;
|
|
use sal_redisclient::*;
|
|
use std::env;
|
|
|
|
#[cfg(test)]
|
|
mod redis_client_tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_env_vars() {
|
|
// Save original REDISDB value to restore later
|
|
let original_redisdb = env::var("REDISDB").ok();
|
|
|
|
// Set test environment variables
|
|
env::set_var("REDISDB", "5");
|
|
|
|
// Test with invalid value
|
|
env::set_var("REDISDB", "invalid");
|
|
|
|
// Test with unset value
|
|
env::remove_var("REDISDB");
|
|
|
|
// Restore original REDISDB value
|
|
if let Some(redisdb) = original_redisdb {
|
|
env::set_var("REDISDB", redisdb);
|
|
} else {
|
|
env::remove_var("REDISDB");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_redis_config_environment_variables() {
|
|
// Test that environment variables are properly handled
|
|
let original_home = env::var("HOME").ok();
|
|
let original_redis_host = env::var("REDIS_HOST").ok();
|
|
let original_redis_port = env::var("REDIS_PORT").ok();
|
|
|
|
// Set test environment variables
|
|
env::set_var("HOME", "/tmp/test");
|
|
env::set_var("REDIS_HOST", "test.redis.com");
|
|
env::set_var("REDIS_PORT", "6380");
|
|
|
|
// Test that the configuration builder respects environment variables
|
|
let config = RedisConfigBuilder::new()
|
|
.host(&env::var("REDIS_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()))
|
|
.port(
|
|
env::var("REDIS_PORT")
|
|
.ok()
|
|
.and_then(|p| p.parse().ok())
|
|
.unwrap_or(6379),
|
|
);
|
|
|
|
assert_eq!(config.host, "test.redis.com");
|
|
assert_eq!(config.port, 6380);
|
|
|
|
// Restore original environment variables
|
|
if let Some(home) = original_home {
|
|
env::set_var("HOME", home);
|
|
} else {
|
|
env::remove_var("HOME");
|
|
}
|
|
if let Some(host) = original_redis_host {
|
|
env::set_var("REDIS_HOST", host);
|
|
} else {
|
|
env::remove_var("REDIS_HOST");
|
|
}
|
|
if let Some(port) = original_redis_port {
|
|
env::set_var("REDIS_PORT", port);
|
|
} else {
|
|
env::remove_var("REDIS_PORT");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_redis_config_validation() {
|
|
// Test configuration validation and edge cases
|
|
|
|
// Test invalid port handling
|
|
let config = RedisConfigBuilder::new().port(0);
|
|
assert_eq!(config.port, 0); // Should accept any port value
|
|
|
|
// Test empty strings
|
|
let config = RedisConfigBuilder::new().host("").username("").password("");
|
|
assert_eq!(config.host, "");
|
|
assert_eq!(config.username, Some("".to_string()));
|
|
assert_eq!(config.password, Some("".to_string()));
|
|
|
|
// Test chaining methods
|
|
let config = RedisConfigBuilder::new()
|
|
.host("localhost")
|
|
.port(6379)
|
|
.db(1)
|
|
.use_tls(true)
|
|
.connection_timeout(30);
|
|
|
|
assert_eq!(config.host, "localhost");
|
|
assert_eq!(config.port, 6379);
|
|
assert_eq!(config.db, 1);
|
|
assert_eq!(config.use_tls, true);
|
|
assert_eq!(config.connection_timeout, Some(30));
|
|
}
|
|
|
|
#[test]
|
|
fn test_redis_config_builder() {
|
|
// Test the Redis configuration builder
|
|
|
|
// Test default values
|
|
let config = RedisConfigBuilder::new();
|
|
assert_eq!(config.host, "127.0.0.1");
|
|
assert_eq!(config.port, 6379);
|
|
assert_eq!(config.db, 0);
|
|
assert_eq!(config.username, None);
|
|
assert_eq!(config.password, None);
|
|
assert_eq!(config.use_tls, false);
|
|
assert_eq!(config.use_unix_socket, false);
|
|
assert_eq!(config.socket_path, None);
|
|
assert_eq!(config.connection_timeout, None);
|
|
|
|
// Test setting values
|
|
let config = RedisConfigBuilder::new()
|
|
.host("redis.example.com")
|
|
.port(6380)
|
|
.db(1)
|
|
.username("user")
|
|
.password("pass")
|
|
.use_tls(true)
|
|
.connection_timeout(30);
|
|
|
|
assert_eq!(config.host, "redis.example.com");
|
|
assert_eq!(config.port, 6380);
|
|
assert_eq!(config.db, 1);
|
|
assert_eq!(config.username, Some("user".to_string()));
|
|
assert_eq!(config.password, Some("pass".to_string()));
|
|
assert_eq!(config.use_tls, true);
|
|
assert_eq!(config.connection_timeout, Some(30));
|
|
|
|
// Test socket path setting
|
|
let config = RedisConfigBuilder::new().socket_path("/tmp/redis.sock");
|
|
|
|
assert_eq!(config.use_unix_socket, true);
|
|
assert_eq!(config.socket_path, Some("/tmp/redis.sock".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_connection_url_building() {
|
|
// Test building connection URLs
|
|
|
|
// Test default URL
|
|
let config = RedisConfigBuilder::new();
|
|
let url = config.build_connection_url();
|
|
assert_eq!(url, "redis://127.0.0.1:6379/0");
|
|
|
|
// Test with authentication
|
|
let config = RedisConfigBuilder::new().username("user").password("pass");
|
|
let url = config.build_connection_url();
|
|
assert_eq!(url, "redis://user:pass@127.0.0.1:6379/0");
|
|
|
|
// Test with password only
|
|
let config = RedisConfigBuilder::new().password("pass");
|
|
let url = config.build_connection_url();
|
|
assert_eq!(url, "redis://:pass@127.0.0.1:6379/0");
|
|
|
|
// Test with TLS
|
|
let config = RedisConfigBuilder::new().use_tls(true);
|
|
let url = config.build_connection_url();
|
|
assert_eq!(url, "rediss://127.0.0.1:6379/0");
|
|
|
|
// Test with Unix socket
|
|
let config = RedisConfigBuilder::new().socket_path("/tmp/redis.sock");
|
|
let url = config.build_connection_url();
|
|
assert_eq!(url, "unix:///tmp/redis.sock");
|
|
}
|
|
}
|
|
|
|
// Integration tests that require a real Redis server
|
|
// These tests will be skipped if Redis is not available
|
|
#[cfg(test)]
|
|
mod redis_integration_tests {
|
|
use super::*;
|
|
|
|
// Helper function to check if Redis is available
|
|
fn is_redis_available() -> bool {
|
|
match get_redis_client() {
|
|
Ok(_) => true,
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_redis_client_integration() {
|
|
if !is_redis_available() {
|
|
println!("Skipping Redis integration tests - Redis server not available");
|
|
return;
|
|
}
|
|
|
|
println!("Running Redis integration tests...");
|
|
|
|
// Test basic operations
|
|
test_basic_redis_operations();
|
|
|
|
// Test more complex operations
|
|
test_hash_operations();
|
|
test_list_operations();
|
|
|
|
// Test error handling
|
|
test_error_handling();
|
|
}
|
|
|
|
fn test_basic_redis_operations() {
|
|
if !is_redis_available() {
|
|
return;
|
|
}
|
|
|
|
// Test setting and getting values
|
|
let client_result = get_redis_client();
|
|
|
|
if client_result.is_err() {
|
|
// Skip the test if we can't connect to Redis
|
|
return;
|
|
}
|
|
|
|
// Create SET command
|
|
let mut set_cmd = redis::cmd("SET");
|
|
set_cmd.arg("test_key").arg("test_value");
|
|
|
|
// Execute SET command
|
|
let set_result: RedisResult<()> = execute(&mut set_cmd);
|
|
assert!(set_result.is_ok());
|
|
|
|
// Create GET command
|
|
let mut get_cmd = redis::cmd("GET");
|
|
get_cmd.arg("test_key");
|
|
|
|
// Execute GET command and check the result
|
|
if let Ok(value) = execute::<String>(&mut get_cmd) {
|
|
assert_eq!(value, "test_value");
|
|
}
|
|
|
|
// Test expiration
|
|
let mut expire_cmd = redis::cmd("EXPIRE");
|
|
expire_cmd.arg("test_key").arg(1); // Expire in 1 second
|
|
let expire_result: RedisResult<i32> = execute(&mut expire_cmd);
|
|
assert!(expire_result.is_ok());
|
|
assert_eq!(expire_result.unwrap(), 1);
|
|
|
|
// Sleep for 2 seconds to let the key expire
|
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
|
|
|
// Check that the key has expired
|
|
let mut exists_cmd = redis::cmd("EXISTS");
|
|
exists_cmd.arg("test_key");
|
|
let exists_result: RedisResult<i32> = execute(&mut exists_cmd);
|
|
assert!(exists_result.is_ok());
|
|
assert_eq!(exists_result.unwrap(), 0);
|
|
|
|
// Clean up
|
|
let _: RedisResult<()> = execute(&mut redis::cmd("DEL").arg("test_key"));
|
|
}
|
|
|
|
fn test_hash_operations() {
|
|
if !is_redis_available() {
|
|
return;
|
|
}
|
|
|
|
// Test hash operations
|
|
let hash_key = "test_hash";
|
|
|
|
// Set hash fields
|
|
let mut hset_cmd = redis::cmd("HSET");
|
|
hset_cmd
|
|
.arg(hash_key)
|
|
.arg("field1")
|
|
.arg("value1")
|
|
.arg("field2")
|
|
.arg("value2");
|
|
let hset_result: RedisResult<i32> = execute(&mut hset_cmd);
|
|
assert!(hset_result.is_ok());
|
|
assert_eq!(hset_result.unwrap(), 2);
|
|
|
|
// Get hash field
|
|
let mut hget_cmd = redis::cmd("HGET");
|
|
hget_cmd.arg(hash_key).arg("field1");
|
|
let hget_result: RedisResult<String> = execute(&mut hget_cmd);
|
|
assert!(hget_result.is_ok());
|
|
assert_eq!(hget_result.unwrap(), "value1");
|
|
|
|
// Get all hash fields
|
|
let mut hgetall_cmd = redis::cmd("HGETALL");
|
|
hgetall_cmd.arg(hash_key);
|
|
let hgetall_result: RedisResult<Vec<String>> = execute(&mut hgetall_cmd);
|
|
assert!(hgetall_result.is_ok());
|
|
let hgetall_values = hgetall_result.unwrap();
|
|
assert_eq!(hgetall_values.len(), 4); // field1, value1, field2, value2
|
|
|
|
// Delete hash field
|
|
let mut hdel_cmd = redis::cmd("HDEL");
|
|
hdel_cmd.arg(hash_key).arg("field1");
|
|
let hdel_result: RedisResult<i32> = execute(&mut hdel_cmd);
|
|
assert!(hdel_result.is_ok());
|
|
assert_eq!(hdel_result.unwrap(), 1);
|
|
|
|
// Clean up
|
|
let _: RedisResult<()> = execute(&mut redis::cmd("DEL").arg(hash_key));
|
|
}
|
|
|
|
fn test_list_operations() {
|
|
if !is_redis_available() {
|
|
return;
|
|
}
|
|
|
|
// Test list operations
|
|
let list_key = "test_list";
|
|
|
|
// Push items to list
|
|
let mut rpush_cmd = redis::cmd("RPUSH");
|
|
rpush_cmd
|
|
.arg(list_key)
|
|
.arg("item1")
|
|
.arg("item2")
|
|
.arg("item3");
|
|
let rpush_result: RedisResult<i32> = execute(&mut rpush_cmd);
|
|
assert!(rpush_result.is_ok());
|
|
assert_eq!(rpush_result.unwrap(), 3);
|
|
|
|
// Get list length
|
|
let mut llen_cmd = redis::cmd("LLEN");
|
|
llen_cmd.arg(list_key);
|
|
let llen_result: RedisResult<i32> = execute(&mut llen_cmd);
|
|
assert!(llen_result.is_ok());
|
|
assert_eq!(llen_result.unwrap(), 3);
|
|
|
|
// Get list range
|
|
let mut lrange_cmd = redis::cmd("LRANGE");
|
|
lrange_cmd.arg(list_key).arg(0).arg(-1);
|
|
let lrange_result: RedisResult<Vec<String>> = execute(&mut lrange_cmd);
|
|
assert!(lrange_result.is_ok());
|
|
let lrange_values = lrange_result.unwrap();
|
|
assert_eq!(lrange_values.len(), 3);
|
|
assert_eq!(lrange_values[0], "item1");
|
|
assert_eq!(lrange_values[1], "item2");
|
|
assert_eq!(lrange_values[2], "item3");
|
|
|
|
// Pop item from list
|
|
let mut lpop_cmd = redis::cmd("LPOP");
|
|
lpop_cmd.arg(list_key);
|
|
let lpop_result: RedisResult<String> = execute(&mut lpop_cmd);
|
|
assert!(lpop_result.is_ok());
|
|
assert_eq!(lpop_result.unwrap(), "item1");
|
|
|
|
// Clean up
|
|
let _: RedisResult<()> = execute(&mut redis::cmd("DEL").arg(list_key));
|
|
}
|
|
|
|
fn test_error_handling() {
|
|
if !is_redis_available() {
|
|
return;
|
|
}
|
|
|
|
// Test error handling
|
|
|
|
// Test invalid command
|
|
let mut invalid_cmd = redis::cmd("INVALID_COMMAND");
|
|
let invalid_result: RedisResult<()> = execute(&mut invalid_cmd);
|
|
assert!(invalid_result.is_err());
|
|
|
|
// Test wrong data type
|
|
let key = "test_wrong_type";
|
|
|
|
// Set a string value
|
|
let mut set_cmd = redis::cmd("SET");
|
|
set_cmd.arg(key).arg("string_value");
|
|
let set_result: RedisResult<()> = execute(&mut set_cmd);
|
|
assert!(set_result.is_ok());
|
|
|
|
// Try to use a hash command on a string
|
|
let mut hget_cmd = redis::cmd("HGET");
|
|
hget_cmd.arg(key).arg("field");
|
|
let hget_result: RedisResult<String> = execute(&mut hget_cmd);
|
|
assert!(hget_result.is_err());
|
|
|
|
// Clean up
|
|
let _: RedisResult<()> = execute(&mut redis::cmd("DEL").arg(key));
|
|
}
|
|
}
|