cloudreve-api 0.8.4

A Rust library for interacting with Cloudreve API
Documentation
use cloudreve_api::{CloudreveClient, Error, Result};
use std::time::Duration;

#[cfg(test)]
mod error_handling_tests {
    use super::*;
    use reqwest::Client;

    #[tokio::test]
    async fn test_error_enum_variants() -> Result<()> {
        let _json_error = Error::Json(serde_json::Error::io(std::io::Error::other("test")));
        let _io_error = Error::Io(std::io::Error::other("test"));
        let _api_error = Error::Api {
            code: 404,
            message: "Not Found".to_string(),
        };
        let _auth_error = Error::Auth("Authentication failed".to_string());
        let _invalid_response_error = Error::InvalidResponse("Invalid response".to_string());
        let _invalid_timestamp_error = Error::InvalidTimestamp("Invalid timestamp".to_string());

        let error_msg = format!("{}", _api_error);
        assert!(error_msg.contains("API error"));

        Ok(())
    }

    #[test]
    fn test_error_display() {
        let api_error = Error::Api {
            code: 401,
            message: "Unauthorized".to_string(),
        };
        let error_str = format!("{}", api_error);
        assert!(error_str.contains("API error"));
        assert!(error_str.contains("Unauthorized"));
        assert!(error_str.contains("401"));
    }

    #[tokio::test]
    async fn test_client_with_invalid_url() -> Result<()> {
        let client = CloudreveClient::new("https://invalid-url-123456789.com");

        let result = client.ping().await;
        assert!(result.is_err());

        Ok(())
    }

    #[tokio::test]
    async fn test_http_timeout_errors() -> Result<()> {
        let http_client = Client::builder()
            .timeout(Duration::from_millis(1))
            .build()
            .unwrap();

        let client = CloudreveClient {
            base_url: "https://httpbin.org/delay/10".to_string(),
            http_client,
            token: None,
            refresh_token: None,
        };

        let result = client.ping().await;
        assert!(result.is_err());

        if let Err(error) = result {
            match error {
                Error::Http(_) => {}
                _ => panic!("Expected HTTP error for timeout, got: {:?}", error),
            }
        }

        Ok(())
    }

    #[tokio::test]
    async fn test_network_connection_errors() -> Result<()> {
        let client = CloudreveClient::new("http://10.255.255.1");

        let result = client.ping().await;
        assert!(result.is_err());

        Ok(())
    }

    #[tokio::test]
    async fn test_json_deserialization_errors() -> Result<()> {
        let client = CloudreveClient::new("https://httpbin.org");

        let result = client.get::<String>("/html").await;
        assert!(result.is_err());

        if let Err(error) = result {
            match error {
                Error::Json(_) => {}
                Error::Http(_) => {}
                Error::Api { .. } => {}
                _ => panic!("Expected JSON, HTTP, or API error, got: {:?}", error),
            }
        }

        Ok(())
    }

    #[tokio::test]
    async fn test_api_error_responses() -> Result<()> {
        let client = CloudreveClient::new("https://httpbin.org");

        let result = client.get::<String>("/status/404").await;
        assert!(result.is_err());

        Ok(())
    }

    #[tokio::test]
    async fn test_parameter_validation_edge_cases() -> Result<()> {
        let client = CloudreveClient::new("https://invalid-domain-for-testing.com");

        let result = client.get::<String>("").await;
        assert!(result.is_err());

        let long_path = "/".to_string() + &"x".repeat(10000);
        let result = client.get::<String>(&long_path).await;
        assert!(result.is_err());

        Ok(())
    }

    #[tokio::test]
    async fn test_boundary_value_parameters() -> Result<()> {
        let client = CloudreveClient::new("https://httpbin.org");

        let _result = client.get::<String>("/get?param=").await;

        let long_content = "x".repeat(1000);
        let _result = client
            .get::<String>(&format!("/get?data={}", long_content))
            .await;

        Ok(())
    }

    #[tokio::test]
    async fn test_concurrent_access_error_handling() -> Result<()> {
        let client = CloudreveClient::new("https://invalid-domain-for-testing.com");

        let mut handles = vec![];

        for _ in 0..10 {
            let client_clone = client.clone();
            let handle = tokio::spawn(async move { client_clone.ping().await });
            handles.push(handle);
        }

        for handle in handles {
            let result = handle.await.unwrap();
            assert!(result.is_err());
        }

        Ok(())
    }

    #[tokio::test]
    async fn test_authentication_error_scenarios() -> Result<()> {
        let mut client = CloudreveClient::new("https://httpbin.org");
        client.set_token("invalid_token_for_testing".to_string());

        let _result = client.get::<serde_json::Value>("/bearer").await;

        Ok(())
    }

    #[tokio::test]
    async fn test_empty_and_whitespace_inputs() -> Result<()> {
        let client = CloudreveClient::new("https://invalid-domain.com");

        let test_cases = vec!["", " ", "  ", "\t", "\n", "\r\n"];

        for test_case in test_cases {
            let _result = client.get::<String>(test_case).await;
        }

        Ok(())
    }

    #[tokio::test]
    async fn test_rate_limit_simulation() -> Result<()> {
        let client = CloudreveClient::new("https://httpbin.org");

        let mut results = Vec::new();
        for _ in 0..5 {
            let result = client.get::<String>("/status/200").await;
            results.push(result);
        }

        Ok(())
    }

    #[tokio::test]
    async fn test_io_error_scenarios() -> Result<()> {
        let client = CloudreveClient::new("https://httpbin.org");

        let _result = client.get::<String>("/%zz").await;

        Ok(())
    }

    #[tokio::test]
    async fn test_retry_mechanism_under_failure() -> Result<()> {
        let client = CloudreveClient::new("https://invalid-domain-that-does-not-exist.com");

        for _ in 0..3 {
            let result = client.ping().await;
            assert!(result.is_err());
        }

        Ok(())
    }
}