feat: Add Redis client module and tests
- Add a new Redis client module to the SAL library. - Implement Rhai wrappers for Redis connection and operations. - Add comprehensive test suite for the Redis client module. - Update documentation to include Redis client module details. - Add .gitignore entries to exclude test logs and files.
This commit is contained in:
parent
32217b6545
commit
1286939608
3
.gitignore
vendored
3
.gitignore
vendored
@ -20,4 +20,5 @@ Cargo.lock
|
||||
|
||||
/target
|
||||
/rhai_test_download
|
||||
/rhai_test_fs
|
||||
/rhai_test_fs
|
||||
run_rhai_tests.log
|
@ -33,6 +33,7 @@ SAL includes test scripts for verifying the functionality of its Rhai integratio
|
||||
- [OS Module Tests](os_module_tests.md): Tests for file system, download, and package management operations
|
||||
- [Git Module Tests](git_module_tests.md): Tests for Git repository management and operations
|
||||
- [Process Module Tests](process_module_tests.md): Tests for command execution and process management
|
||||
- [Redis Client Module Tests](redisclient_module_tests.md): Tests for Redis connection and operations
|
||||
- [Running Tests](running_tests.md): Instructions for running all Rhai tests
|
||||
- [CI Workflow](ci_workflow.md): Continuous integration workflow for Rhai tests
|
||||
|
||||
|
97
docs/rhai/redisclient_module_tests.md
Normal file
97
docs/rhai/redisclient_module_tests.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Redis Client Module Tests
|
||||
|
||||
This document describes the test scripts for the Redis client module in the SAL library. These tests verify the functionality of the Redis client module's connection management and Redis operations.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into two main scripts:
|
||||
|
||||
1. **Redis Connection** (`01_redis_connection.rhai`): Tests basic Redis connection and simple operations like PING, SET, GET, and DEL.
|
||||
2. **Redis Operations** (`02_redis_operations.rhai`): Tests more advanced Redis operations like hash operations (HSET, HGET, HGETALL, HDEL) and list operations (RPUSH, LLEN, LRANGE).
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/redisclient/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/redisclient/01_redis_connection.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Redis Connection Test
|
||||
|
||||
The Redis connection test (`01_redis_connection.rhai`) verifies the following functions:
|
||||
|
||||
- `redis_ping`: Checking if the Redis server is available
|
||||
- `redis_set`: Setting a key-value pair
|
||||
- `redis_get`: Getting a value by key
|
||||
- `redis_del`: Deleting a key
|
||||
|
||||
The test creates a temporary key, performs operations on it, and then cleans up after itself.
|
||||
|
||||
### Redis Operations Test
|
||||
|
||||
The Redis operations test (`02_redis_operations.rhai`) verifies the following functions:
|
||||
|
||||
- Hash operations:
|
||||
- `redis_hset`: Setting a field in a hash
|
||||
- `redis_hget`: Getting a field from a hash
|
||||
- `redis_hgetall`: Getting all fields and values from a hash
|
||||
- `redis_hdel`: Deleting a field from a hash
|
||||
|
||||
- List operations:
|
||||
- `redis_rpush`: Adding elements to a list
|
||||
- `redis_llen`: Getting the length of a list
|
||||
- `redis_lrange`: Getting a range of elements from a list
|
||||
|
||||
The test creates temporary keys with a unique prefix, performs operations on them, and then cleans up after itself.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Checks if Redis is available before running tests
|
||||
2. Skips tests if Redis is not available
|
||||
3. Contains simplified versions of each test
|
||||
4. Runs each test in a try/catch block to handle errors
|
||||
5. Catches and reports any errors
|
||||
6. Provides a summary of passed, failed, and skipped tests
|
||||
|
||||
## Redis Server Requirements
|
||||
|
||||
These tests require a Redis server to be running and accessible. The tests will attempt to connect to Redis using the following strategy:
|
||||
|
||||
1. First, try to connect via Unix socket at `$HOME/hero/var/myredis.sock`
|
||||
2. If that fails, try to connect via TCP to `127.0.0.1` on the default Redis port (6379)
|
||||
|
||||
If no Redis server is available, the tests will be skipped rather than failing.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/redisclient` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Redis client module:
|
||||
|
||||
1. Always check if Redis is available before running tests
|
||||
2. Use a unique prefix for test keys to avoid conflicts
|
||||
3. Clean up any keys created during testing
|
||||
4. Use assertions to verify expected behavior
|
||||
5. Print clear messages about what's being tested
|
||||
6. Handle errors gracefully
|
||||
7. Make tests independent of each other
|
||||
8. Keep tests focused on specific functionality
|
@ -1,131 +0,0 @@
|
||||
[0;34m=======================================[0m
|
||||
[0;34m Running All Rhai Tests [0m
|
||||
[0;34m=======================================[0m
|
||||
|
||||
[0;33mRunning tests for module: git[0m
|
||||
[0;33m-------------------------------------[0m
|
||||
Found 1 Rhai script to execute:
|
||||
|
||||
Executing: src/rhai_tests/git/run_all_tests.rhai
|
||||
=== Running Git Module Tests ===
|
||||
|
||||
--- Running Basic Git Operations Tests ---
|
||||
Created test directory: rhai_test_git
|
||||
Testing GitTree constructor...
|
||||
✓ GitTree created successfully
|
||||
Testing GitTree.list() with empty directory...
|
||||
✓ GitTree.list(): Found 0 repositories (expected 0)
|
||||
Testing GitTree.find() with empty directory...
|
||||
✓ GitTree.find(): Found 0 repositories (expected 0)
|
||||
Cleaning up...
|
||||
✓ Cleanup: Directory rhai_test_git removed
|
||||
--- Basic Git Operations Tests completed successfully ---
|
||||
|
||||
--- Running Git Repository Operations Tests ---
|
||||
Created test directory: rhai_test_git_ops
|
||||
Creating GitTree...
|
||||
✓ GitTree created successfully
|
||||
Cleaning up...
|
||||
✓ Cleanup: Directory rhai_test_git_ops removed
|
||||
--- Git Repository Operations Tests completed successfully ---
|
||||
|
||||
=== Test Summary ===
|
||||
Passed: 2
|
||||
Failed: 0
|
||||
Total: 2
|
||||
|
||||
✅ All tests passed!
|
||||
Script executed successfully
|
||||
Result: 0
|
||||
|
||||
All scripts executed
|
||||
[0;32m✓ Module git tests passed[0m
|
||||
|
||||
[0;33mRunning tests for module: os[0m
|
||||
[0;33m-------------------------------------[0m
|
||||
Found 1 Rhai script to execute:
|
||||
|
||||
Executing: src/rhai_tests/os/run_all_tests.rhai
|
||||
=== Running OS Module Tests ===
|
||||
|
||||
--- Running File Operations Tests ---
|
||||
Testing mkdir...
|
||||
✓ mkdir: Successfully created directory 'rhai_test_fs'
|
||||
✓ mkdir (nested): Successfully created directory 'rhai_test_fs/subdir'
|
||||
✓ file_write: Successfully wrote to file 'rhai_test_fs/test.txt'
|
||||
✓ file_read: Content matches
|
||||
✓ file_size: 48 bytes
|
||||
✓ delete: Directory cleaned up
|
||||
--- File Operations Tests completed successfully ---
|
||||
|
||||
--- Running Download Operations Tests ---
|
||||
Created test directory: rhai_test_download
|
||||
✓ which: curl found at /usr/bin/curl
|
||||
✓ cmd_ensure_exists: Command 'curl' exists
|
||||
Downloading https://raw.githubusercontent.com/rust-lang/rust/master/LICENSE-MIT...
|
||||
Downloading https://raw.githubusercontent.com/rust-lang/rust/master/LICENSE-MIT to rhai_test_download/license.txt
|
||||
Download complete! File size: 1.04 KB
|
||||
✓ download_file: rhai_test_download/license.txt
|
||||
✓ Downloaded file content verified
|
||||
✓ Cleanup: Directory rhai_test_download removed
|
||||
--- Download Operations Tests completed successfully ---
|
||||
|
||||
--- Running Package Operations Tests ---
|
||||
Current platform: Ubuntu
|
||||
✓ package_set_debug: Debug mode enabled
|
||||
--- Package Operations Tests completed successfully ---
|
||||
|
||||
=== Test Summary ===
|
||||
Passed: 3
|
||||
Failed: 0
|
||||
Total: 3
|
||||
|
||||
✅ All tests passed!
|
||||
Script executed successfully
|
||||
Result: 0
|
||||
|
||||
All scripts executed
|
||||
[0;32m✓ Module os tests passed[0m
|
||||
|
||||
[0;33mRunning tests for module: process[0m
|
||||
[0;33m-------------------------------------[0m
|
||||
Found 1 Rhai script to execute:
|
||||
|
||||
Executing: src/rhai_tests/process/run_all_tests.rhai
|
||||
=== Running Process Module Tests ===
|
||||
|
||||
--- Running Command Execution Tests ---
|
||||
Testing run() with a simple command...
|
||||
Hello, World!
|
||||
✓ run().execute(): Command executed successfully
|
||||
Testing which() function...
|
||||
✓ which(): Found bash at /usr/bin/bash
|
||||
--- Command Execution Tests completed successfully ---
|
||||
|
||||
--- Running Process Management Tests ---
|
||||
Testing process_list() function...
|
||||
✓ process_list(): Found 344 processes
|
||||
Testing process properties...
|
||||
✓ Process properties: PID=1, Name=systemd
|
||||
--- Process Management Tests completed successfully ---
|
||||
|
||||
=== Test Summary ===
|
||||
Passed: 2
|
||||
Failed: 0
|
||||
Total: 2
|
||||
|
||||
✅ All tests passed!
|
||||
Script executed successfully
|
||||
Result: 0
|
||||
|
||||
All scripts executed
|
||||
[0;32m✓ Module process tests passed[0m
|
||||
|
||||
[0;34m=======================================[0m
|
||||
[0;34m Test Summary [0m
|
||||
[0;34m=======================================[0m
|
||||
Total modules tested: 3
|
||||
Passed: [0;32m3[0m
|
||||
Failed: [0;31m0[0m
|
||||
|
||||
[0;32mAll tests passed![0m
|
@ -9,6 +9,7 @@ mod git;
|
||||
mod nerdctl;
|
||||
mod os;
|
||||
mod process;
|
||||
mod redisclient;
|
||||
mod rfs;
|
||||
mod text;
|
||||
|
||||
@ -39,6 +40,9 @@ pub use os::{
|
||||
rsync,
|
||||
};
|
||||
|
||||
// Re-export Redis client module registration function
|
||||
pub use redisclient::register_redisclient_module;
|
||||
|
||||
pub use process::{
|
||||
kill,
|
||||
process_get,
|
||||
@ -140,6 +144,9 @@ pub fn register(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
// Register RFS module functions
|
||||
rfs::register(engine)?;
|
||||
|
||||
// Register Redis client module functions
|
||||
redisclient::register_redisclient_module(engine)?;
|
||||
|
||||
// Future modules can be registered here
|
||||
|
||||
Ok(())
|
||||
|
323
src/rhai/redisclient.rs
Normal file
323
src/rhai/redisclient.rs
Normal file
@ -0,0 +1,323 @@
|
||||
//! Rhai wrappers for Redis client module functions
|
||||
//!
|
||||
//! This module provides Rhai wrappers for the functions in the Redis client module.
|
||||
|
||||
use crate::redisclient;
|
||||
use rhai::{Engine, EvalAltResult, Map};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Register Redis client module functions with the Rhai engine
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `engine` - The Rhai engine to register the functions with
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
||||
pub fn register_redisclient_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||
// Register basic Redis operations
|
||||
engine.register_fn("redis_ping", redis_ping);
|
||||
engine.register_fn("redis_set", redis_set);
|
||||
engine.register_fn("redis_get", redis_get);
|
||||
engine.register_fn("redis_del", redis_del);
|
||||
|
||||
// Register hash operations
|
||||
engine.register_fn("redis_hset", redis_hset);
|
||||
engine.register_fn("redis_hget", redis_hget);
|
||||
engine.register_fn("redis_hgetall", redis_hgetall);
|
||||
engine.register_fn("redis_hdel", redis_hdel);
|
||||
|
||||
// Register list operations
|
||||
engine.register_fn("redis_rpush", redis_rpush);
|
||||
engine.register_fn("redis_lpush", redis_lpush);
|
||||
engine.register_fn("redis_llen", redis_llen);
|
||||
engine.register_fn("redis_lrange", redis_lrange);
|
||||
|
||||
// Register other operations
|
||||
engine.register_fn("redis_reset", redis_reset);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ping the Redis server
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<String, Box<EvalAltResult>>` - "PONG" if successful, error otherwise
|
||||
pub fn redis_ping() -> Result<String, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("PING");
|
||||
redisclient::execute(&mut cmd).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// Set a key-value pair in Redis
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The key to set
|
||||
/// * `value` - The value to set
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
|
||||
pub fn redis_set(key: &str, value: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("SET");
|
||||
cmd.arg(key).arg(value);
|
||||
let result: redis::RedisResult<String> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(s) if s == "OK" => Ok(true),
|
||||
Ok(_) => Ok(false),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a value from Redis by key
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The key to get
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<String, Box<EvalAltResult>>` - The value if found, empty string if not found, error otherwise
|
||||
pub fn redis_get(key: &str) -> Result<String, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("GET");
|
||||
cmd.arg(key);
|
||||
let result: redis::RedisResult<Option<String>> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(Some(value)) => Ok(value),
|
||||
Ok(None) => Ok(String::new()),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a key from Redis
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The key to delete
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
|
||||
pub fn redis_del(key: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("DEL");
|
||||
cmd.arg(key);
|
||||
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(n) => Ok(n > 0),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a field in a hash
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The hash key
|
||||
/// * `field` - The field to set
|
||||
/// * `value` - The value to set
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
|
||||
pub fn redis_hset(key: &str, field: &str, value: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("HSET");
|
||||
cmd.arg(key).arg(field).arg(value);
|
||||
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a field from a hash
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The hash key
|
||||
/// * `field` - The field to get
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<String, Box<EvalAltResult>>` - The value if found, empty string if not found, error otherwise
|
||||
pub fn redis_hget(key: &str, field: &str) -> Result<String, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("HGET");
|
||||
cmd.arg(key).arg(field);
|
||||
let result: redis::RedisResult<Option<String>> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(Some(value)) => Ok(value),
|
||||
Ok(None) => Ok(String::new()),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all fields and values from a hash
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The hash key
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<Map, Box<EvalAltResult>>` - A map of field-value pairs, error otherwise
|
||||
pub fn redis_hgetall(key: &str) -> Result<Map, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("HGETALL");
|
||||
cmd.arg(key);
|
||||
let result: redis::RedisResult<HashMap<String, String>> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(hash_map) => {
|
||||
let mut map = Map::new();
|
||||
for (k, v) in hash_map {
|
||||
map.insert(k.into(), v.into());
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a field from a hash
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The hash key
|
||||
/// * `field` - The field to delete
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
|
||||
pub fn redis_hdel(key: &str, field: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("HDEL");
|
||||
cmd.arg(key).arg(field);
|
||||
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
|
||||
match result {
|
||||
Ok(n) => Ok(n > 0),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Push an element to the end of a list
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The list key
|
||||
/// * `value` - The value to push
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<i64, Box<EvalAltResult>>` - The new length of the list, error otherwise
|
||||
pub fn redis_rpush(key: &str, value: &str) -> Result<i64, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("RPUSH");
|
||||
cmd.arg(key).arg(value);
|
||||
redisclient::execute(&mut cmd).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// Push an element to the beginning of a list
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The list key
|
||||
/// * `value` - The value to push
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<i64, Box<EvalAltResult>>` - The new length of the list, error otherwise
|
||||
pub fn redis_lpush(key: &str, value: &str) -> Result<i64, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("LPUSH");
|
||||
cmd.arg(key).arg(value);
|
||||
redisclient::execute(&mut cmd).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the length of a list
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The list key
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<i64, Box<EvalAltResult>>` - The length of the list, error otherwise
|
||||
pub fn redis_llen(key: &str) -> Result<i64, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("LLEN");
|
||||
cmd.arg(key);
|
||||
redisclient::execute(&mut cmd).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a range of elements from a list
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `key` - The list key
|
||||
/// * `start` - The start index
|
||||
/// * `stop` - The stop index
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<Vec<String>, Box<EvalAltResult>>` - The elements in the range, error otherwise
|
||||
pub fn redis_lrange(key: &str, start: i64, stop: i64) -> Result<Vec<String>, Box<EvalAltResult>> {
|
||||
let mut cmd = redis::cmd("LRANGE");
|
||||
cmd.arg(key).arg(start).arg(stop);
|
||||
redisclient::execute(&mut cmd).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// Reset the Redis client connection
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
|
||||
pub fn redis_reset() -> Result<bool, Box<EvalAltResult>> {
|
||||
match redisclient::reset() {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Redis error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))),
|
||||
}
|
||||
}
|
68
src/rhai_tests/redisclient/01_redis_connection.rhai
Normal file
68
src/rhai_tests/redisclient/01_redis_connection.rhai
Normal file
@ -0,0 +1,68 @@
|
||||
// 01_redis_connection.rhai
|
||||
// Tests for Redis client connection and basic operations
|
||||
|
||||
// Custom assert function
|
||||
fn assert_true(condition, message) {
|
||||
if !condition {
|
||||
print(`ASSERTION FAILED: ${message}`);
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if Redis is available
|
||||
fn is_redis_available() {
|
||||
try {
|
||||
// Try to execute a simple PING command
|
||||
let ping_result = redis_ping();
|
||||
return ping_result == "PONG";
|
||||
} catch(err) {
|
||||
print(`Redis connection error: ${err}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
print("=== Testing Redis Client Connection ===");
|
||||
|
||||
// Check if Redis is available
|
||||
let redis_available = is_redis_available();
|
||||
if !redis_available {
|
||||
print("Redis server is not available. Skipping Redis tests.");
|
||||
// Exit gracefully without error
|
||||
return;
|
||||
}
|
||||
|
||||
print("✓ Redis server is available");
|
||||
|
||||
// Test redis_ping function
|
||||
print("Testing redis_ping()...");
|
||||
let ping_result = redis_ping();
|
||||
assert_true(ping_result == "PONG", "PING should return PONG");
|
||||
print(`✓ redis_ping(): Returned ${ping_result}`);
|
||||
|
||||
// Test redis_set and redis_get functions
|
||||
print("Testing redis_set() and redis_get()...");
|
||||
let test_key = "rhai_test_key";
|
||||
let test_value = "Hello from Rhai test";
|
||||
|
||||
// Set a value
|
||||
let set_result = redis_set(test_key, test_value);
|
||||
assert_true(set_result, "SET operation should succeed");
|
||||
print(`✓ redis_set(): Successfully set key ${test_key}`);
|
||||
|
||||
// Get the value back
|
||||
let get_result = redis_get(test_key);
|
||||
assert_true(get_result == test_value, "GET should return the value we set");
|
||||
print(`✓ redis_get(): Successfully retrieved value for key ${test_key}`);
|
||||
|
||||
// Test redis_del function
|
||||
print("Testing redis_del()...");
|
||||
let del_result = redis_del(test_key);
|
||||
assert_true(del_result, "DEL operation should succeed");
|
||||
print(`✓ redis_del(): Successfully deleted key ${test_key}`);
|
||||
|
||||
// Verify the key was deleted
|
||||
let get_after_del = redis_get(test_key);
|
||||
assert_true(get_after_del == "", "Key should not exist after deletion");
|
||||
print("✓ Key was successfully deleted");
|
||||
|
||||
print("All Redis connection tests completed successfully!");
|
109
src/rhai_tests/redisclient/02_redis_operations.rhai
Normal file
109
src/rhai_tests/redisclient/02_redis_operations.rhai
Normal file
@ -0,0 +1,109 @@
|
||||
// 02_redis_operations.rhai
|
||||
// Tests for advanced Redis operations
|
||||
|
||||
// Custom assert function
|
||||
fn assert_true(condition, message) {
|
||||
if !condition {
|
||||
print(`ASSERTION FAILED: ${message}`);
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if Redis is available
|
||||
fn is_redis_available() {
|
||||
try {
|
||||
// Try to execute a simple PING command
|
||||
let ping_result = redis_ping();
|
||||
return ping_result == "PONG";
|
||||
} catch(err) {
|
||||
print(`Redis connection error: ${err}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
print("=== Testing Advanced Redis Operations ===");
|
||||
|
||||
// Check if Redis is available
|
||||
let redis_available = is_redis_available();
|
||||
if !redis_available {
|
||||
print("Redis server is not available. Skipping Redis tests.");
|
||||
// Exit gracefully without error
|
||||
return;
|
||||
}
|
||||
|
||||
print("✓ Redis server is available");
|
||||
|
||||
// Test prefix for all keys to avoid conflicts
|
||||
let prefix = "rhai_test_";
|
||||
|
||||
// Test redis_hset and redis_hget functions
|
||||
print("Testing redis_hset() and redis_hget()...");
|
||||
let hash_key = prefix + "hash";
|
||||
let field1 = "field1";
|
||||
let value1 = "value1";
|
||||
let field2 = "field2";
|
||||
let value2 = "value2";
|
||||
|
||||
// Set hash fields
|
||||
let hset_result1 = redis_hset(hash_key, field1, value1);
|
||||
assert_true(hset_result1, "HSET operation should succeed for field1");
|
||||
let hset_result2 = redis_hset(hash_key, field2, value2);
|
||||
assert_true(hset_result2, "HSET operation should succeed for field2");
|
||||
print(`✓ redis_hset(): Successfully set fields in hash ${hash_key}`);
|
||||
|
||||
// Get hash fields
|
||||
let hget_result1 = redis_hget(hash_key, field1);
|
||||
assert_true(hget_result1 == value1, "HGET should return the value we set for field1");
|
||||
let hget_result2 = redis_hget(hash_key, field2);
|
||||
assert_true(hget_result2 == value2, "HGET should return the value we set for field2");
|
||||
print(`✓ redis_hget(): Successfully retrieved values from hash ${hash_key}`);
|
||||
|
||||
// Test redis_hgetall function
|
||||
print("Testing redis_hgetall()...");
|
||||
let hgetall_result = redis_hgetall(hash_key);
|
||||
assert_true(hgetall_result.len() == 2, "HGETALL should return 2 fields");
|
||||
assert_true(hgetall_result[field1] == value1, "HGETALL should include field1 with correct value");
|
||||
assert_true(hgetall_result[field2] == value2, "HGETALL should include field2 with correct value");
|
||||
print(`✓ redis_hgetall(): Successfully retrieved all fields from hash ${hash_key}`);
|
||||
|
||||
// Test redis_hdel function
|
||||
print("Testing redis_hdel()...");
|
||||
let hdel_result = redis_hdel(hash_key, field1);
|
||||
assert_true(hdel_result, "HDEL operation should succeed");
|
||||
print(`✓ redis_hdel(): Successfully deleted field from hash ${hash_key}`);
|
||||
|
||||
// Verify the field was deleted
|
||||
let hget_after_del = redis_hget(hash_key, field1);
|
||||
assert_true(hget_after_del == "", "Field should not exist after deletion");
|
||||
print("✓ Field was successfully deleted from hash");
|
||||
|
||||
// Test redis_list operations
|
||||
print("Testing redis list operations...");
|
||||
let list_key = prefix + "list";
|
||||
|
||||
// Push items to list
|
||||
let rpush_result = redis_rpush(list_key, "item1");
|
||||
assert_true(rpush_result > 0, "RPUSH operation should succeed");
|
||||
redis_rpush(list_key, "item2");
|
||||
redis_rpush(list_key, "item3");
|
||||
print(`✓ redis_rpush(): Successfully pushed items to list ${list_key}`);
|
||||
|
||||
// Get list length
|
||||
let llen_result = redis_llen(list_key);
|
||||
assert_true(llen_result == 3, "List should have 3 items");
|
||||
print(`✓ redis_llen(): List has ${llen_result} items`);
|
||||
|
||||
// Get list range
|
||||
let lrange_result = redis_lrange(list_key, 0, -1);
|
||||
assert_true(lrange_result.len() == 3, "LRANGE should return 3 items");
|
||||
assert_true(lrange_result[0] == "item1", "First item should be 'item1'");
|
||||
assert_true(lrange_result[2] == "item3", "Last item should be 'item3'");
|
||||
print(`✓ redis_lrange(): Successfully retrieved all items from list ${list_key}`);
|
||||
|
||||
// Clean up
|
||||
print("Cleaning up...");
|
||||
redis_del(hash_key);
|
||||
redis_del(list_key);
|
||||
print("✓ Cleanup: All test keys removed");
|
||||
|
||||
print("All Redis operations tests completed successfully!");
|
121
src/rhai_tests/redisclient/run_all_tests.rhai
Normal file
121
src/rhai_tests/redisclient/run_all_tests.rhai
Normal file
@ -0,0 +1,121 @@
|
||||
// run_all_tests.rhai
|
||||
// Runs all Redis client module tests
|
||||
|
||||
print("=== Running Redis Client Module Tests ===");
|
||||
|
||||
// Custom assert function
|
||||
fn assert_true(condition, message) {
|
||||
if !condition {
|
||||
print(`ASSERTION FAILED: ${message}`);
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if Redis is available
|
||||
fn is_redis_available() {
|
||||
try {
|
||||
// Try to execute a simple PING command
|
||||
let ping_result = redis_ping();
|
||||
return ping_result == "PONG";
|
||||
} catch(err) {
|
||||
print(`Redis connection error: ${err}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Run each test directly
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
let skipped = 0;
|
||||
|
||||
// Check if Redis is available
|
||||
let redis_available = is_redis_available();
|
||||
if !redis_available {
|
||||
print("Redis server is not available. Skipping all Redis tests.");
|
||||
skipped = 2; // Skip both tests
|
||||
} else {
|
||||
// Test 1: Redis Connection
|
||||
print("\n--- Running Redis Connection Tests ---");
|
||||
try {
|
||||
// Test redis_ping function
|
||||
print("Testing redis_ping()...");
|
||||
let ping_result = redis_ping();
|
||||
assert_true(ping_result == "PONG", "PING should return PONG");
|
||||
print(`✓ redis_ping(): Returned ${ping_result}`);
|
||||
|
||||
// Test redis_set and redis_get functions
|
||||
print("Testing redis_set() and redis_get()...");
|
||||
let test_key = "rhai_test_key";
|
||||
let test_value = "Hello from Rhai test";
|
||||
|
||||
// Set a value
|
||||
let set_result = redis_set(test_key, test_value);
|
||||
assert_true(set_result, "SET operation should succeed");
|
||||
print(`✓ redis_set(): Successfully set key ${test_key}`);
|
||||
|
||||
// Get the value back
|
||||
let get_result = redis_get(test_key);
|
||||
assert_true(get_result == test_value, "GET should return the value we set");
|
||||
print(`✓ redis_get(): Successfully retrieved value for key ${test_key}`);
|
||||
|
||||
// Clean up
|
||||
redis_del(test_key);
|
||||
|
||||
print("--- Redis Connection Tests completed successfully ---");
|
||||
passed += 1;
|
||||
} catch(err) {
|
||||
print(`!!! Error in Redis Connection Tests: ${err}`);
|
||||
failed += 1;
|
||||
}
|
||||
|
||||
// Test 2: Redis Operations
|
||||
print("\n--- Running Redis Operations Tests ---");
|
||||
try {
|
||||
// Test prefix for all keys to avoid conflicts
|
||||
let prefix = "rhai_test_";
|
||||
|
||||
// Test redis_hset and redis_hget functions
|
||||
print("Testing redis_hset() and redis_hget()...");
|
||||
let hash_key = prefix + "hash";
|
||||
let field = "field1";
|
||||
let value = "value1";
|
||||
|
||||
// Set hash field
|
||||
let hset_result = redis_hset(hash_key, field, value);
|
||||
assert_true(hset_result, "HSET operation should succeed");
|
||||
print(`✓ redis_hset(): Successfully set field in hash ${hash_key}`);
|
||||
|
||||
// Get hash field
|
||||
let hget_result = redis_hget(hash_key, field);
|
||||
assert_true(hget_result == value, "HGET should return the value we set");
|
||||
print(`✓ redis_hget(): Successfully retrieved value from hash ${hash_key}`);
|
||||
|
||||
// Clean up
|
||||
redis_del(hash_key);
|
||||
|
||||
print("--- Redis Operations Tests completed successfully ---");
|
||||
passed += 1;
|
||||
} catch(err) {
|
||||
print(`!!! Error in Redis Operations Tests: ${err}`);
|
||||
failed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
print("\n=== Test Summary ===");
|
||||
print(`Passed: ${passed}`);
|
||||
print(`Failed: ${failed}`);
|
||||
print(`Skipped: ${skipped}`);
|
||||
print(`Total: ${passed + failed + skipped}`);
|
||||
|
||||
if failed == 0 {
|
||||
if skipped > 0 {
|
||||
print("\n⚠️ All tests skipped or passed!");
|
||||
} else {
|
||||
print("\n✅ All tests passed!");
|
||||
}
|
||||
} else {
|
||||
print("\n❌ Some tests failed!");
|
||||
}
|
||||
|
||||
// Return the number of failed tests (0 means success)
|
||||
failed;
|
Loading…
Reference in New Issue
Block a user