oxcache 0.2.0

A high-performance multi-level cache library for Rust with L1 (memory) and L2 (Redis) caching.
// Copyright (c) 2025-2026, Kirky.X
//
// MIT License
//
// 安全验收测试工具 - 使用新API

use crate::common;

#[cfg(feature = "redis")]
use oxcache::backend::memory::RedisBackend;
#[cfg(feature = "redis")]
use oxcache::backend::{CacheReader, CacheWriter};
use std::time::Duration;
use tokio::time::timeout;

/// 安全验收测试配置
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct SecurityTestConfig {
    test_tls: bool,
    test_authentication: bool,
    test_authorization: bool,
    test_data_encryption: bool,
    test_connection_security: bool,
    test_error_handling: bool,
    test_logging_security: bool,
    test_configuration_security: bool,
    timeout_seconds: u64,
}

impl Default for SecurityTestConfig {
    fn default() -> Self {
        Self {
            test_tls: true,
            test_authentication: true,
            test_authorization: true,
            test_data_encryption: true,
            test_connection_security: true,
            test_error_handling: true,
            test_logging_security: true,
            test_configuration_security: true,
            timeout_seconds: 30,
        }
    }
}

/// 测试 Redis 连接安全
#[tokio::test]
async fn test_redis_connection_security() {
    if !common::is_redis_available().await {
        println!("跳过测试:Redis不可用");
        return;
    }

    let redis_url = "redis://127.0.0.1:6379";
    let backend = RedisBackend::new(redis_url).await;
    if backend.is_err() {
        println!("跳过测试:Redis连接失败(可能需要认证或TLS)");
        return;
    }
}

/// 测试 Redis 认证
#[tokio::test]
async fn test_redis_authentication() {
    let no_password_url = "redis://127.0.0.1:6379";
    let result = RedisBackend::new(no_password_url).await;
    if result.is_err() {
        println!("认证测试:连接失败(可能需要认证)");
    }
}

/// 测试 Redis 命令执行安全
#[tokio::test]
async fn test_redis_command_security() {
    if !common::is_redis_available().await {
        println!("跳过测试:Redis不可用");
        return;
    }

    let redis_url = "redis://127.0.0.1:6379";
    let backend = match RedisBackend::new(redis_url).await {
        Ok(b) => b,
        Err(e) => {
            println!("跳过测试:Redis连接失败 - {}", e);
            return;
        }
    };

    let test_key = "security:test:key";
    let test_value = b"test_value";

    let set_result = backend
        .set(test_key, test_value.to_vec(), Some(Duration::from_secs(60)))
        .await;
    assert!(set_result.is_ok(), "SET operation should succeed");

    let get_result = backend.get(test_key).await;
    assert!(get_result.is_ok(), "GET operation should succeed");

    let _ = backend.delete(test_key).await;
}

/// 测试 Redis 超时设置
#[tokio::test]
async fn test_redis_timeout_settings() {
    let redis_url = "redis://127.0.0.1:6379";
    let backend = RedisBackend::new(redis_url).await;

    if let Ok(b) = backend {
        let ping_result = timeout(Duration::from_secs(10), b.ping()).await;
        let success = matches!(ping_result, Ok(Ok(_)));
        assert!(success, "Ping should complete within timeout");
    }
}

/// 测试连接字符串安全
#[tokio::test]
async fn test_connection_string_security() {
    let standard_url = "redis://127.0.0.1:6379";
    let result = RedisBackend::new(standard_url).await;
    if result.is_err() {
        println!("连接字符串测试:连接失败(可能需要认证或TLS)");
    }
}

/// 测试错误处理安全
#[tokio::test]
async fn test_error_handling_security() {
    let invalid_url = "redis://invalid:port";
    let result = RedisBackend::new(invalid_url).await;
    assert!(result.is_err(), "Invalid connection should return error, not panic");
}

// ponytail: deleted liar test that always passed on a literal string

/// 测试数据加密
#[tokio::test]
async fn test_data_encryption() {
    if !common::is_redis_available().await {
        println!("跳过测试:Redis不可用");
        return;
    }

    let redis_url = "redis://127.0.0.1:6379";
    let backend = match RedisBackend::new(redis_url).await {
        Ok(b) => b,
        Err(e) => {
            println!("跳过测试:Redis连接失败 - {}", e);
            return;
        }
    };

    let test_key = "encryption:test:binary";
    let test_data = vec![0u8; 256];

    let set_result = backend
        .set(test_key, test_data.clone(), Some(Duration::from_secs(60)))
        .await;
    assert!(set_result.is_ok(), "Binary data SET should succeed");

    let get_result = backend.get(test_key).await;
    assert!(get_result.is_ok(), "Binary data GET should succeed");

    if let Ok(Some(retrieved)) = get_result {
        assert_eq!(retrieved, test_data, "Retrieved data should match original");
    }

    let _ = backend.delete(test_key).await;
}