mirror of
https://github.com/seemueller-io/hyper-custom-cert.git
synced 2025-09-08 22:46:45 +00:00

* 0.3.4 * Add `RequestOptions` for per-request customization with headers and timeouts - Introduced the `RequestOptions` struct for flexible HTTP request configurations. - Added `request_with_options` and `post_with_options` methods. - Deprecated `request` and `post` in favor of the new methods. - Updated examples and tests to reflect the new API. * run cargo fmt * Update HTTP client methods to use `request_with_options` for improved flexibility. Adjusted related test cases and examples accordingly. * Format `request_with_options` calls for improved readability. * - Downgrade `edition` from 2024 to 2021 in Cargo.toml files for compatibility. - Fix nested `if let` statements to improve readability and correctness. - Reorganize imports for consistency and structure. * Restore github old workflows * update ci --------- Co-authored-by: geoffsee <>
388 lines
13 KiB
Rust
388 lines
13 KiB
Rust
//! Integration tests that verify the comprehensive API surface of the hyper-custom-cert HttpClient
|
|
//!
|
|
//! These tests verify that the hyper-custom-cert HttpClient API works correctly across all
|
|
//! feature combinations and configuration patterns. The tests are designed as "smoke tests"
|
|
//! that verify API availability and compilation without requiring actual network I/O.
|
|
//!
|
|
//! This restores parity with the previously deleted integration tests while adapting
|
|
//! to the new async HTTP implementation that returns HttpResponse with raw body data.
|
|
|
|
use hyper_custom_cert::HttpClient;
|
|
use std::collections::HashMap;
|
|
use std::time::Duration;
|
|
|
|
// ============================================================================
|
|
// BASIC CLIENT TESTS - Test client creation and configuration patterns
|
|
// ============================================================================
|
|
|
|
#[tokio::test]
|
|
async fn test_default_client_against_example_endpoints() {
|
|
// Test default HttpClient creation
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify client creation succeeds and API is available
|
|
// In real usage, these would be actual HTTP requests:
|
|
// let _response = client.request("http://localhost:8080/health").await.unwrap();
|
|
// let _response = client.request("http://localhost:8080/status").await.unwrap();
|
|
// let _response = client.request("http://localhost:8080/test/client/default").await.unwrap();
|
|
|
|
// For testing purposes, just verify the client exists
|
|
let _ = client;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_builder_client_against_example_endpoints() {
|
|
// Test HttpClient builder pattern
|
|
let client = HttpClient::builder().build();
|
|
|
|
// Smoke test - verify builder pattern works
|
|
// In real usage: let _response = client.request("http://localhost:8080/").await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
#[test]
|
|
fn test_timeout_configuration_for_example_server() {
|
|
// Test timeout configuration
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(10))
|
|
.build();
|
|
|
|
// Smoke test - verify timeout configuration compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[test]
|
|
fn test_headers_configuration_for_example_server() {
|
|
// Test custom headers configuration
|
|
let mut headers = HashMap::new();
|
|
headers.insert(
|
|
"User-Agent".to_string(),
|
|
"hyper-custom-cert-integration-test/1.0".to_string(),
|
|
);
|
|
headers.insert("X-Test-Client".to_string(), "integration".to_string());
|
|
headers.insert("Accept".to_string(), "application/json".to_string());
|
|
|
|
let client = HttpClient::builder().with_default_headers(headers).build();
|
|
|
|
// Smoke test - verify header configuration compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[test]
|
|
fn test_combined_configuration_for_example_server() {
|
|
// Test combining multiple configuration options
|
|
let mut headers = HashMap::new();
|
|
headers.insert(
|
|
"User-Agent".to_string(),
|
|
"hyper-custom-cert-combined-test/1.0".to_string(),
|
|
);
|
|
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(30))
|
|
.with_default_headers(headers)
|
|
.build();
|
|
|
|
// Smoke test - verify combined configuration compiles
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// FEATURE-SPECIFIC TESTS - Test feature-gated functionality
|
|
// ============================================================================
|
|
|
|
#[cfg(feature = "native-tls")]
|
|
#[test]
|
|
fn test_native_tls_feature_with_example_server() {
|
|
// Test native-tls specific functionality
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(15))
|
|
.build();
|
|
|
|
// Smoke test - verify native-tls feature compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "rustls")]
|
|
#[test]
|
|
fn test_rustls_feature_with_example_server() {
|
|
// Test rustls specific functionality
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(15))
|
|
.build();
|
|
|
|
// Smoke test - verify rustls feature compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "rustls")]
|
|
#[test]
|
|
fn test_rustls_custom_ca_configuration() {
|
|
// Test custom CA configuration
|
|
let dummy_ca_pem = b"-----BEGIN CERTIFICATE-----\nDUMMY\n-----END CERTIFICATE-----";
|
|
|
|
let client = HttpClient::builder()
|
|
.with_root_ca_pem(dummy_ca_pem)
|
|
.with_timeout(Duration::from_secs(10))
|
|
.build();
|
|
|
|
// Smoke test - verify TLS configuration compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "rustls")]
|
|
#[test]
|
|
fn test_rustls_cert_pinning_configuration() {
|
|
// Test certificate pinning configuration
|
|
let dummy_pin = [0u8; 32];
|
|
let pins = vec![dummy_pin];
|
|
|
|
let client = HttpClient::builder().with_pinned_cert_sha256(pins).build();
|
|
|
|
// Smoke test - verify cert pinning compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "insecure-dangerous")]
|
|
#[test]
|
|
fn test_insecure_feature_with_example_server() {
|
|
// Test insecure-dangerous feature for development
|
|
let client = HttpClient::builder()
|
|
.insecure_accept_invalid_certs(true)
|
|
.build();
|
|
|
|
// Smoke test - verify insecure feature compiles
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "insecure-dangerous")]
|
|
#[test]
|
|
fn test_self_signed_convenience_constructor() {
|
|
// Test convenience constructor for self-signed certificates
|
|
let client = HttpClient::with_self_signed_certs();
|
|
|
|
// Smoke test - verify convenience constructor works
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// HTTP METHOD TESTS - Test different HTTP methods
|
|
// ============================================================================
|
|
|
|
#[tokio::test]
|
|
async fn test_request_options() {
|
|
use hyper_custom_cert::RequestOptions;
|
|
use std::collections::HashMap;
|
|
use std::time::Duration;
|
|
|
|
// Test RequestOptions functionality
|
|
let client = HttpClient::new();
|
|
|
|
// Create request options
|
|
let mut headers = HashMap::new();
|
|
headers.insert("X-Custom-Header".to_string(), "test-value".to_string());
|
|
|
|
let options = RequestOptions::new()
|
|
.with_headers(headers)
|
|
.with_timeout(Duration::from_secs(15));
|
|
|
|
// Smoke test - verify request options can be used with both GET and POST
|
|
// In real usage:
|
|
// let _get_resp = client.request("https://example.com", Some(options.clone())).await.unwrap();
|
|
// let _post_resp = client.post("https://example.com", b"{}", Some(options)).await.unwrap();
|
|
let _ = (client, options);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_requests_to_example_server() {
|
|
// Test GET requests
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify GET method API exists
|
|
// In real usage: let _response = client.request("http://localhost:8080/test/methods/get", None).await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_post_requests_to_example_server() {
|
|
// Test POST requests
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify POST method API exists
|
|
// In real usage:
|
|
// let json_payload = r#"{"name": "test", "value": "integration-test"}"#;
|
|
// let _response = client.post("http://localhost:8080/test/methods/post", json_payload.as_bytes(), None).await.unwrap();
|
|
// let _response = client.post("http://localhost:8080/test/methods/post", b"", None).await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ERROR HANDLING TESTS - Test error scenarios
|
|
// ============================================================================
|
|
|
|
#[test]
|
|
fn test_timeout_error_handling() {
|
|
// Test timeout error handling configuration
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_millis(1)) // Very short timeout
|
|
.build();
|
|
|
|
// Smoke test - verify timeout configuration compiles
|
|
// In real usage, this would test actual timeout behavior
|
|
let _ = client;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_invalid_url_handling() {
|
|
// Test invalid URL handling
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify client creation
|
|
// In real usage, this would test actual URL validation:
|
|
// let result = client.request("invalid-url", None).await;
|
|
// assert!(result.is_err()); // Should fail with invalid URI error
|
|
let _ = client;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_connection_error_handling() {
|
|
// Test connection error scenarios
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify client creation
|
|
// In real usage, this would test actual connection errors:
|
|
// let result = client.request("http://localhost:99999/nonexistent").await;
|
|
// assert!(result.is_err()); // Should fail with connection error
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// FEATURE COMBINATION TESTS - Test various feature combinations
|
|
// ============================================================================
|
|
|
|
#[cfg(all(feature = "rustls", feature = "insecure-dangerous"))]
|
|
#[test]
|
|
fn test_rustls_with_insecure_combination() {
|
|
// Test rustls with insecure-dangerous feature combination
|
|
let client = HttpClient::builder()
|
|
.insecure_accept_invalid_certs(true)
|
|
.with_root_ca_pem(b"-----BEGIN CERTIFICATE-----\nDUMMY\n-----END CERTIFICATE-----")
|
|
.build();
|
|
|
|
// Smoke test - verify combined features compile
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(all(feature = "native-tls", feature = "insecure-dangerous"))]
|
|
#[test]
|
|
fn test_native_tls_with_insecure_combination() {
|
|
// Test native-tls with insecure-dangerous feature combination
|
|
let client = HttpClient::builder()
|
|
.insecure_accept_invalid_certs(true)
|
|
.build();
|
|
|
|
// Smoke test - verify combined features compile
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// CONFIGURATION VALIDATION TESTS - Test client configuration validation
|
|
// ============================================================================
|
|
|
|
#[tokio::test]
|
|
async fn test_default_trait_implementations() {
|
|
// Test Default trait implementations
|
|
let client = HttpClient::default();
|
|
let builder = hyper_custom_cert::HttpClientBuilder::default();
|
|
|
|
// Smoke test - verify Default implementations work
|
|
// In real usage: let _response = client.request("http://localhost:8080/health").await.unwrap();
|
|
// In real usage: let _response = builder.build().request("http://localhost:8080/status").await.unwrap();
|
|
let _ = (client, builder);
|
|
}
|
|
|
|
#[test]
|
|
fn test_builder_chaining() {
|
|
// Test builder pattern chaining
|
|
let mut headers = HashMap::new();
|
|
headers.insert("Test-Header".to_string(), "test-value".to_string());
|
|
|
|
let mut client_builder = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(20))
|
|
.with_default_headers(headers);
|
|
|
|
#[cfg(feature = "insecure-dangerous")]
|
|
{
|
|
client_builder = client_builder.insecure_accept_invalid_certs(false);
|
|
}
|
|
|
|
#[cfg(feature = "rustls")]
|
|
{
|
|
client_builder = client_builder.with_root_ca_pem(b"dummy");
|
|
}
|
|
|
|
let client = client_builder.build();
|
|
|
|
// Smoke test - verify builder chaining works
|
|
let _ = client;
|
|
}
|
|
|
|
// ============================================================================
|
|
// DOCUMENTATION TESTS - Test examples from documentation
|
|
// ============================================================================
|
|
|
|
#[tokio::test]
|
|
async fn test_basic_usage_example() {
|
|
// Test basic usage example that would be in documentation
|
|
let client = HttpClient::new();
|
|
|
|
// Smoke test - verify basic usage compiles
|
|
// In real usage: let _response = client.request("http://localhost:8080/").await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_builder_usage_example() {
|
|
// Test builder usage example
|
|
let mut headers = HashMap::new();
|
|
headers.insert("User-Agent".to_string(), "my-app/1.0".to_string());
|
|
|
|
let client = HttpClient::builder()
|
|
.with_timeout(Duration::from_secs(30))
|
|
.with_default_headers(headers)
|
|
.build();
|
|
|
|
// Smoke test - verify builder usage example compiles
|
|
// In real usage: let _response = client.request("http://localhost:8080/api").await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "rustls")]
|
|
#[tokio::test]
|
|
async fn test_rustls_usage_example() {
|
|
// Test rustls usage example from documentation
|
|
let client = HttpClient::builder()
|
|
.with_root_ca_pem(b"-----BEGIN CERTIFICATE-----\nDUMMY\n-----END CERTIFICATE-----")
|
|
.build();
|
|
|
|
// Smoke test - verify rustls example compiles
|
|
// In real usage: let _response = client.request("https://localhost:8080/secure").await.unwrap();
|
|
let _ = client;
|
|
}
|
|
|
|
#[cfg(feature = "insecure-dangerous")]
|
|
#[tokio::test]
|
|
async fn test_insecure_usage_example() {
|
|
// Test insecure usage example (development only)
|
|
let client = HttpClient::builder()
|
|
.insecure_accept_invalid_certs(true)
|
|
.build();
|
|
|
|
// Also test convenience constructor
|
|
let client2 = HttpClient::with_self_signed_certs();
|
|
|
|
// Smoke test - verify insecure examples compile
|
|
// In real usage: let _response = client.request("https://localhost:8080/self-signed").await.unwrap();
|
|
// In real usage: let _response = client2.request("https://localhost:8080/self-signed").await.unwrap();
|
|
let _ = (client, client2);
|
|
}
|