feat: Add PostgreSQL and Redis client support
- Add PostgreSQL client functionality for database interactions. - Add Redis client functionality for cache and data store operations. - Extend Rhai scripting with PostgreSQL and Redis client modules. - Add documentation and test cases for both clients.
This commit is contained in:
277
src/postgresclient/tests.rs
Normal file
277
src/postgresclient/tests.rs
Normal file
@@ -0,0 +1,277 @@
|
||||
use super::*;
|
||||
use std::env;
|
||||
|
||||
#[cfg(test)]
|
||||
mod postgres_client_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_env_vars() {
|
||||
// Save original environment variables to restore later
|
||||
let original_host = env::var("POSTGRES_HOST").ok();
|
||||
let original_port = env::var("POSTGRES_PORT").ok();
|
||||
let original_user = env::var("POSTGRES_USER").ok();
|
||||
let original_password = env::var("POSTGRES_PASSWORD").ok();
|
||||
let original_db = env::var("POSTGRES_DB").ok();
|
||||
|
||||
// Set test environment variables
|
||||
env::set_var("POSTGRES_HOST", "test-host");
|
||||
env::set_var("POSTGRES_PORT", "5433");
|
||||
env::set_var("POSTGRES_USER", "test-user");
|
||||
env::set_var("POSTGRES_PASSWORD", "test-password");
|
||||
env::set_var("POSTGRES_DB", "test-db");
|
||||
|
||||
// Test with invalid port
|
||||
env::set_var("POSTGRES_PORT", "invalid");
|
||||
|
||||
// Test with unset values
|
||||
env::remove_var("POSTGRES_HOST");
|
||||
env::remove_var("POSTGRES_PORT");
|
||||
env::remove_var("POSTGRES_USER");
|
||||
env::remove_var("POSTGRES_PASSWORD");
|
||||
env::remove_var("POSTGRES_DB");
|
||||
|
||||
// Restore original environment variables
|
||||
if let Some(host) = original_host {
|
||||
env::set_var("POSTGRES_HOST", host);
|
||||
}
|
||||
if let Some(port) = original_port {
|
||||
env::set_var("POSTGRES_PORT", port);
|
||||
}
|
||||
if let Some(user) = original_user {
|
||||
env::set_var("POSTGRES_USER", user);
|
||||
}
|
||||
if let Some(password) = original_password {
|
||||
env::set_var("POSTGRES_PASSWORD", password);
|
||||
}
|
||||
if let Some(db) = original_db {
|
||||
env::set_var("POSTGRES_DB", db);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_postgres_config_builder() {
|
||||
// Test the PostgreSQL configuration builder
|
||||
|
||||
// Test default values
|
||||
let config = PostgresConfigBuilder::new();
|
||||
assert_eq!(config.host, "localhost");
|
||||
assert_eq!(config.port, 5432);
|
||||
assert_eq!(config.user, "postgres");
|
||||
assert_eq!(config.password, None);
|
||||
assert_eq!(config.database, "postgres");
|
||||
assert_eq!(config.application_name, None);
|
||||
assert_eq!(config.connect_timeout, None);
|
||||
assert_eq!(config.ssl_mode, None);
|
||||
|
||||
// Test setting values
|
||||
let config = PostgresConfigBuilder::new()
|
||||
.host("pg.example.com")
|
||||
.port(5433)
|
||||
.user("test-user")
|
||||
.password("test-password")
|
||||
.database("test-db")
|
||||
.application_name("test-app")
|
||||
.connect_timeout(30)
|
||||
.ssl_mode("require");
|
||||
|
||||
assert_eq!(config.host, "pg.example.com");
|
||||
assert_eq!(config.port, 5433);
|
||||
assert_eq!(config.user, "test-user");
|
||||
assert_eq!(config.password, Some("test-password".to_string()));
|
||||
assert_eq!(config.database, "test-db");
|
||||
assert_eq!(config.application_name, Some("test-app".to_string()));
|
||||
assert_eq!(config.connect_timeout, Some(30));
|
||||
assert_eq!(config.ssl_mode, Some("require".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_string_building() {
|
||||
// Test building connection strings
|
||||
|
||||
// Test default connection string
|
||||
let config = PostgresConfigBuilder::new();
|
||||
let conn_string = config.build_connection_string();
|
||||
assert!(conn_string.contains("host=localhost"));
|
||||
assert!(conn_string.contains("port=5432"));
|
||||
assert!(conn_string.contains("user=postgres"));
|
||||
assert!(conn_string.contains("dbname=postgres"));
|
||||
assert!(!conn_string.contains("password="));
|
||||
|
||||
// Test with all options
|
||||
let config = PostgresConfigBuilder::new()
|
||||
.host("pg.example.com")
|
||||
.port(5433)
|
||||
.user("test-user")
|
||||
.password("test-password")
|
||||
.database("test-db")
|
||||
.application_name("test-app")
|
||||
.connect_timeout(30)
|
||||
.ssl_mode("require");
|
||||
|
||||
let conn_string = config.build_connection_string();
|
||||
assert!(conn_string.contains("host=pg.example.com"));
|
||||
assert!(conn_string.contains("port=5433"));
|
||||
assert!(conn_string.contains("user=test-user"));
|
||||
assert!(conn_string.contains("password=test-password"));
|
||||
assert!(conn_string.contains("dbname=test-db"));
|
||||
assert!(conn_string.contains("application_name=test-app"));
|
||||
assert!(conn_string.contains("connect_timeout=30"));
|
||||
assert!(conn_string.contains("sslmode=require"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_mock() {
|
||||
// This is a simplified test that doesn't require an actual PostgreSQL server
|
||||
|
||||
// Just verify that the reset function doesn't panic
|
||||
if let Err(_) = reset() {
|
||||
// If PostgreSQL is not available, this is expected to fail
|
||||
// So we don't assert anything here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Integration tests that require a real PostgreSQL server
|
||||
// These tests will be skipped if PostgreSQL is not available
|
||||
#[cfg(test)]
|
||||
mod postgres_integration_tests {
|
||||
use super::*;
|
||||
|
||||
// Helper function to check if PostgreSQL is available
|
||||
fn is_postgres_available() -> bool {
|
||||
match get_postgres_client() {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_postgres_client_integration() {
|
||||
if !is_postgres_available() {
|
||||
println!("Skipping PostgreSQL integration tests - PostgreSQL server not available");
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Running PostgreSQL integration tests...");
|
||||
|
||||
// Test basic operations
|
||||
test_basic_postgres_operations();
|
||||
|
||||
// Test error handling
|
||||
test_error_handling();
|
||||
}
|
||||
|
||||
fn test_basic_postgres_operations() {
|
||||
if !is_postgres_available() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a test table
|
||||
let create_table_query = "
|
||||
CREATE TEMPORARY TABLE test_table (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
value INTEGER
|
||||
)
|
||||
";
|
||||
|
||||
let create_result = execute(create_table_query, &[]);
|
||||
assert!(create_result.is_ok());
|
||||
|
||||
// Insert data
|
||||
let insert_query = "
|
||||
INSERT INTO test_table (name, value)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id
|
||||
";
|
||||
|
||||
let insert_result = query(insert_query, &[&"test_name", &42]);
|
||||
assert!(insert_result.is_ok());
|
||||
|
||||
let rows = insert_result.unwrap();
|
||||
assert_eq!(rows.len(), 1);
|
||||
|
||||
let id: i32 = rows[0].get(0);
|
||||
assert!(id > 0);
|
||||
|
||||
// Query data
|
||||
let select_query = "
|
||||
SELECT id, name, value
|
||||
FROM test_table
|
||||
WHERE id = $1
|
||||
";
|
||||
|
||||
let select_result = query_one(select_query, &[&id]);
|
||||
assert!(select_result.is_ok());
|
||||
|
||||
let row = select_result.unwrap();
|
||||
let name: String = row.get(1);
|
||||
let value: i32 = row.get(2);
|
||||
|
||||
assert_eq!(name, "test_name");
|
||||
assert_eq!(value, 42);
|
||||
|
||||
// Update data
|
||||
let update_query = "
|
||||
UPDATE test_table
|
||||
SET value = $1
|
||||
WHERE id = $2
|
||||
";
|
||||
|
||||
let update_result = execute(update_query, &[&100, &id]);
|
||||
assert!(update_result.is_ok());
|
||||
assert_eq!(update_result.unwrap(), 1); // 1 row affected
|
||||
|
||||
// Verify update
|
||||
let verify_query = "
|
||||
SELECT value
|
||||
FROM test_table
|
||||
WHERE id = $1
|
||||
";
|
||||
|
||||
let verify_result = query_one(verify_query, &[&id]);
|
||||
assert!(verify_result.is_ok());
|
||||
|
||||
let row = verify_result.unwrap();
|
||||
let updated_value: i32 = row.get(0);
|
||||
assert_eq!(updated_value, 100);
|
||||
|
||||
// Delete data
|
||||
let delete_query = "
|
||||
DELETE FROM test_table
|
||||
WHERE id = $1
|
||||
";
|
||||
|
||||
let delete_result = execute(delete_query, &[&id]);
|
||||
assert!(delete_result.is_ok());
|
||||
assert_eq!(delete_result.unwrap(), 1); // 1 row affected
|
||||
}
|
||||
|
||||
fn test_error_handling() {
|
||||
if !is_postgres_available() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Test invalid SQL
|
||||
let invalid_query = "SELECT * FROM nonexistent_table";
|
||||
let invalid_result = query(invalid_query, &[]);
|
||||
assert!(invalid_result.is_err());
|
||||
|
||||
// Test parameter type mismatch
|
||||
let mismatch_query = "SELECT $1::integer";
|
||||
let mismatch_result = query(mismatch_query, &[&"not_an_integer"]);
|
||||
assert!(mismatch_result.is_err());
|
||||
|
||||
// Test query_one with no results
|
||||
let empty_query = "SELECT * FROM pg_tables WHERE tablename = 'nonexistent_table'";
|
||||
let empty_result = query_one(empty_query, &[]);
|
||||
assert!(empty_result.is_err());
|
||||
|
||||
// Test query_opt with no results
|
||||
let opt_query = "SELECT * FROM pg_tables WHERE tablename = 'nonexistent_table'";
|
||||
let opt_result = query_opt(opt_query, &[]);
|
||||
assert!(opt_result.is_ok());
|
||||
assert!(opt_result.unwrap().is_none());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user