Ensure the all the actions defined in the ci.yml workflow pass locally.

This commit is contained in:
geoffsee
2025-08-14 16:36:56 -04:00
parent 39d19f45e2
commit 24d7d0bf5a
6 changed files with 1437 additions and 217 deletions

1219
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error as StdError; use std::error::Error as StdError;
use std::fmt; use std::fmt;
#[cfg(feature = "rustls")]
use std::fs; use std::fs;
#[cfg(feature = "rustls")]
use std::path::Path; use std::path::Path;
use std::time::Duration; use std::time::Duration;
@@ -265,9 +267,13 @@ impl HttpClientBuilder {
/// ``` /// ```
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
pub fn with_root_ca_file<P: AsRef<Path>>(mut self, path: P) -> Self { pub fn with_root_ca_file<P: AsRef<Path>>(mut self, path: P) -> Self {
let pem_bytes = fs::read(path.as_ref()) let pem_bytes = fs::read(path.as_ref()).unwrap_or_else(|e| {
.unwrap_or_else(|e| panic!("Failed to read CA certificate file '{}': {}", panic!(
path.as_ref().display(), e)); "Failed to read CA certificate file '{}': {}",
path.as_ref().display(),
e
)
});
self.root_ca_pem = Some(pem_bytes); self.root_ca_pem = Some(pem_bytes);
self self
} }
@@ -407,13 +413,12 @@ Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTest...
// Write test certificate to temporary file // Write test certificate to temporary file
{ {
let mut file = fs::File::create(&cert_file).expect("Failed to create temp cert file"); let mut file = fs::File::create(&cert_file).expect("Failed to create temp cert file");
file.write_all(test_cert).expect("Failed to write cert to temp file"); file.write_all(test_cert)
.expect("Failed to write cert to temp file");
} }
// Test that the builder can read the certificate file // Test that the builder can read the certificate file
let client = HttpClient::builder() let client = HttpClient::builder().with_root_ca_file(&cert_file).build();
.with_root_ca_file(&cert_file)
.build();
// Verify the certificate was loaded // Verify the certificate was loaded
assert!(client.root_ca_pem.is_some()); assert!(client.root_ca_pem.is_some());

View File

@@ -3,37 +3,33 @@
//! These tests verify that the library works correctly with only the default //! These tests verify that the library works correctly with only the default
//! features enabled (native-tls backend using OS trust store). //! features enabled (native-tls backend using OS trust store).
use hyper_custom_cert::{HttpClient, HttpClientBuilder}; use hyper_custom_cert::HttpClient;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Duration; use std::time::Duration;
#[test] #[test]
fn default_client_creation() { fn default_client_creation() {
// Test that we can create a client with default features // Test that we can create a client with default features
let client = HttpClient::new(); let _client = HttpClient::new();
// Basic smoke test - the client should be created successfully // Basic smoke test - the client should be created successfully
// In a real scenario, this would make an actual HTTP request // In a real scenario, this would make an actual HTTP request
assert!(true); // Placeholder - client creation succeeded
} }
#[test] #[test]
fn default_client_from_builder() { fn default_client_from_builder() {
// Test builder pattern with default features // Test builder pattern with default features
let client = HttpClient::builder().build(); let _client = HttpClient::builder().build();
// Verify builder works with default features // Verify builder works with default features
assert!(true); // Placeholder - builder succeeded
} }
#[test] #[test]
fn builder_with_timeout() { fn builder_with_timeout() {
// Test timeout configuration with default features // Test timeout configuration with default features
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(30)) .with_timeout(Duration::from_secs(30))
.build(); .build();
assert!(true); // Placeholder - timeout configuration succeeded
} }
#[test] #[test]
@@ -43,11 +39,7 @@ fn builder_with_headers() {
headers.insert("User-Agent".to_string(), "test-agent".to_string()); headers.insert("User-Agent".to_string(), "test-agent".to_string());
headers.insert("Accept".to_string(), "application/json".to_string()); headers.insert("Accept".to_string(), "application/json".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder().with_default_headers(headers).build();
.with_default_headers(headers)
.build();
assert!(true); // Placeholder - header configuration succeeded
} }
#[test] #[test]
@@ -56,24 +48,21 @@ fn builder_combined_configuration() {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
headers.insert("Custom-Header".to_string(), "custom-value".to_string()); headers.insert("Custom-Header".to_string(), "custom-value".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(45)) .with_timeout(Duration::from_secs(45))
.with_default_headers(headers) .with_default_headers(headers)
.build(); .build();
assert!(true); // Placeholder - combined configuration succeeded
} }
#[cfg(feature = "native-tls")] #[cfg(feature = "native-tls")]
#[test] #[test]
fn native_tls_specific_functionality() { fn native_tls_specific_functionality() {
// Test functionality that's specific to native-tls backend // Test functionality that's specific to native-tls backend
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(10)) .with_timeout(Duration::from_secs(10))
.build(); .build();
// This test should only run when native-tls feature is enabled // This test should only run when native-tls feature is enabled
assert!(true); // Placeholder - native-tls specific test
} }
// Test that methods requiring other features are not available // Test that methods requiring other features are not available
@@ -88,7 +77,7 @@ fn rustls_methods_not_available() {
// builder.with_root_ca_file("test.pem"); // builder.with_root_ca_file("test.pem");
// builder.with_pinned_cert_sha256(vec![[0u8; 32]]); // builder.with_pinned_cert_sha256(vec![[0u8; 32]]);
assert!(true); // If this compiles, the test passes // If this compiles, the test passes
} }
#[test] #[test]
@@ -99,12 +88,11 @@ fn insecure_methods_not_available() {
// The following would cause compilation errors if insecure-dangerous feature is not enabled: // The following would cause compilation errors if insecure-dangerous feature is not enabled:
// builder.insecure_accept_invalid_certs(true); // builder.insecure_accept_invalid_certs(true);
assert!(true); // If this compiles, the test passes // If this compiles, the test passes
} }
#[test] #[test]
fn default_client_static_method() { fn default_client_static_method() {
// Test the static convenience method // Test the static convenience method
let client = HttpClient::default(); let _client = HttpClient::default();
assert!(true); // Placeholder - default() method succeeded
} }

View File

@@ -4,11 +4,18 @@
//! combinations of features enabled/disabled, ensuring proper conditional //! combinations of features enabled/disabled, ensuring proper conditional
//! compilation and feature interactions. //! compilation and feature interactions.
use hyper_custom_cert::{HttpClient, HttpClientBuilder}; use hyper_custom_cert::HttpClient;
#[cfg(any(
all(feature = "rustls", feature = "insecure-dangerous"),
all(feature = "native-tls", feature = "insecure-dangerous"),
not(any(feature = "rustls", feature = "insecure-dangerous")),
all(feature = "native-tls", feature = "rustls", feature = "insecure-dangerous")
))]
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Duration; use std::time::Duration;
// Test CA certificate for combination tests // Test CA certificate for combination tests
#[allow(dead_code)]
const TEST_CA_PEM: &[u8] = b"-----BEGIN CERTIFICATE----- const TEST_CA_PEM: &[u8] = b"-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
@@ -23,32 +30,31 @@ CgKCAQEAuuExKtKjKEw91uR8gqyUZx+wW3qZjUHq3oLe+RxbEUVFWApwrKE3XxKJ
#[test] #[test]
fn rustls_and_insecure_combination() { fn rustls_and_insecure_combination() {
// Test combining rustls custom CA with insecure certificate acceptance // Test combining rustls custom CA with insecure certificate acceptance
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - rustls + insecure combination // Test passes if compilation succeeds
} }
#[cfg(all(feature = "rustls", feature = "insecure-dangerous"))] #[cfg(all(feature = "rustls", feature = "insecure-dangerous"))]
#[test] #[test]
fn rustls_pinning_and_insecure_combination() { fn rustls_pinning_and_insecure_combination() {
// Test combining certificate pinning with insecure mode (unusual but valid) // Test combining certificate pinning with insecure mode (unusual but valid)
let pins = vec![ let pins = vec![[
[0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], ]];
];
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_pinned_cert_sha256(pins) .with_pinned_cert_sha256(pins)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.with_timeout(Duration::from_secs(30)) .with_timeout(Duration::from_secs(30))
.build(); .build();
assert!(true); // Placeholder - pinning + insecure combination // Test passes if compilation succeeds
} }
#[cfg(all(feature = "rustls", feature = "insecure-dangerous"))] #[cfg(all(feature = "rustls", feature = "insecure-dangerous"))]
@@ -60,7 +66,7 @@ fn full_rustls_insecure_configuration() {
let pins = vec![[0u8; 32]]; let pins = vec![[0u8; 32]];
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(45)) .with_timeout(Duration::from_secs(45))
.with_default_headers(headers) .with_default_headers(headers)
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
@@ -69,7 +75,7 @@ fn full_rustls_insecure_configuration() {
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - full rustls + insecure configuration // Test passes if compilation succeeds
} }
// Test with native-tls + insecure-dangerous (default + insecure) // Test with native-tls + insecure-dangerous (default + insecure)
@@ -77,12 +83,12 @@ fn full_rustls_insecure_configuration() {
#[test] #[test]
fn native_tls_and_insecure_combination() { fn native_tls_and_insecure_combination() {
// Test combining native-tls (default) with insecure mode // Test combining native-tls (default) with insecure mode
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(20)) .with_timeout(Duration::from_secs(20))
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - native-tls + insecure combination // Test passes if compilation succeeds
} }
#[cfg(all(feature = "native-tls", feature = "insecure-dangerous"))] #[cfg(all(feature = "native-tls", feature = "insecure-dangerous"))]
@@ -93,12 +99,12 @@ fn native_tls_insecure_with_headers() {
headers.insert("Authorization".to_string(), "Bearer test".to_string()); headers.insert("Authorization".to_string(), "Bearer test".to_string());
headers.insert("Content-Type".to_string(), "application/json".to_string()); headers.insert("Content-Type".to_string(), "application/json".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_default_headers(headers) .with_default_headers(headers)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - native-tls + insecure with headers // Test passes if compilation succeeds
} }
// Test with no optional features (base functionality only) // Test with no optional features (base functionality only)
@@ -106,11 +112,11 @@ fn native_tls_insecure_with_headers() {
#[test] #[test]
fn minimal_feature_set() { fn minimal_feature_set() {
// Test with only the default native-tls feature // Test with only the default native-tls feature
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(30)) .with_timeout(Duration::from_secs(30))
.build(); .build();
assert!(true); // Placeholder - minimal feature set // Test passes if compilation succeeds
} }
#[cfg(not(any(feature = "rustls", feature = "insecure-dangerous")))] #[cfg(not(any(feature = "rustls", feature = "insecure-dangerous")))]
@@ -120,16 +126,20 @@ fn minimal_with_headers_only() {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
headers.insert("User-Agent".to_string(), "minimal-client".to_string()); headers.insert("User-Agent".to_string(), "minimal-client".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_default_headers(headers) .with_default_headers(headers)
.with_timeout(Duration::from_millis(5000)) .with_timeout(Duration::from_millis(5000))
.build(); .build();
assert!(true); // Placeholder - minimal with headers // Test passes if compilation succeeds
} }
// Test with all features enabled // Test with all features enabled
#[cfg(all(feature = "native-tls", feature = "rustls", feature = "insecure-dangerous"))] #[cfg(all(
feature = "native-tls",
feature = "rustls",
feature = "insecure-dangerous"
))]
#[test] #[test]
fn all_features_enabled() { fn all_features_enabled() {
// Test when all features are available // Test when all features are available
@@ -138,7 +148,7 @@ fn all_features_enabled() {
let pins = vec![[0x42; 32]]; let pins = vec![[0x42; 32]];
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(60)) .with_timeout(Duration::from_secs(60))
.with_default_headers(headers) .with_default_headers(headers)
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
@@ -146,19 +156,23 @@ fn all_features_enabled() {
.insecure_accept_invalid_certs(false) // Safe default even with insecure available .insecure_accept_invalid_certs(false) // Safe default even with insecure available
.build(); .build();
assert!(true); // Placeholder - all features enabled // Test passes if compilation succeeds
} }
#[cfg(all(feature = "native-tls", feature = "rustls", feature = "insecure-dangerous"))] #[cfg(all(
feature = "native-tls",
feature = "rustls",
feature = "insecure-dangerous"
))]
#[test] #[test]
fn all_features_insecure_enabled() { fn all_features_insecure_enabled() {
// Test all features with insecure mode actually enabled // Test all features with insecure mode actually enabled
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_root_ca_pem(TEST_CA_PEM) // Use PEM instead of file for CI/CD compatibility .with_root_ca_pem(TEST_CA_PEM) // Use PEM instead of file for CI/CD compatibility
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - all features with insecure enabled // Test passes if compilation succeeds
} }
// Test feature availability at compile time // Test feature availability at compile time
@@ -169,24 +183,21 @@ fn feature_availability_check() {
// Always available (default) // Always available (default)
let _default_client = HttpClient::new(); let _default_client = HttpClient::new();
let _builder = HttpClient::builder() let _builder = HttpClient::builder().with_timeout(Duration::from_secs(10));
.with_timeout(Duration::from_secs(10));
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
{ {
// rustls features should be available // rustls features should be available
let _rustls_client = HttpClient::builder() let _rustls_client = HttpClient::builder().with_root_ca_pem(TEST_CA_PEM);
.with_root_ca_pem(TEST_CA_PEM);
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
{ {
// insecure features should be available // insecure features should be available
let _insecure_client = HttpClient::builder() let _insecure_client = HttpClient::builder().insecure_accept_invalid_certs(true);
.insecure_accept_invalid_certs(true);
} }
assert!(true); // Feature availability test completed // Test passes if compilation succeeds
} }
// Test builder method chaining with different feature combinations // Test builder method chaining with different feature combinations
@@ -195,13 +206,13 @@ fn feature_availability_check() {
fn rustls_method_chaining() { fn rustls_method_chaining() {
// Test method chaining with rustls features // Test method chaining with rustls features
// Note: Using only PEM method to avoid file I/O in tests // Note: Using only PEM method to avoid file I/O in tests
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(30)) .with_timeout(Duration::from_secs(30))
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.with_root_ca_pem(TEST_CA_PEM) // Chain multiple PEM calls instead of file .with_root_ca_pem(TEST_CA_PEM) // Chain multiple PEM calls instead of file
.build(); .build();
assert!(true); // Placeholder - rustls method chaining // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
@@ -211,24 +222,24 @@ fn insecure_method_chaining() {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
headers.insert("Test".to_string(), "chaining".to_string()); headers.insert("Test".to_string(), "chaining".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_millis(1000)) .with_timeout(Duration::from_millis(1000))
.with_default_headers(headers) .with_default_headers(headers)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure method chaining // Test passes if compilation succeeds
} }
// Test error conditions with different feature combinations // Test error conditions with different feature combinations
#[test] #[test]
fn basic_error_handling() { fn basic_error_handling() {
// Test basic error handling regardless of features // Test basic error handling regardless of features
let client = HttpClient::new(); let _client = HttpClient::new();
// This would test actual error scenarios in a real implementation // This would test actual error scenarios in a real implementation
// For now, just verify the client was created successfully // For now, just verify the client was created successfully
assert!(true); // Placeholder - basic error handling // Test passes if compilation succeeds
} }
#[cfg(all(feature = "rustls", feature = "insecure-dangerous"))] #[cfg(all(feature = "rustls", feature = "insecure-dangerous"))]
@@ -257,5 +268,5 @@ fn complex_configuration_order() {
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - configuration order test // Test passes if compilation succeeds
} }

View File

@@ -6,42 +6,40 @@
//! ⚠️ WARNING: The insecure-dangerous feature disables important security checks. //! ⚠️ WARNING: The insecure-dangerous feature disables important security checks.
//! Never use this in production environments! //! Never use this in production environments!
use hyper_custom_cert::{HttpClient, HttpClientBuilder}; use hyper_custom_cert::HttpClient;
use std::collections::HashMap;
use std::time::Duration;
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
#[test] #[test]
fn insecure_accept_invalid_certs_enabled() { fn insecure_accept_invalid_certs_enabled() {
// Test enabling insecure certificate acceptance (development only!) // Test enabling insecure certificate acceptance (development only!)
let client = HttpClient::builder() let _client = HttpClient::builder()
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure mode enabled // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
#[test] #[test]
fn insecure_accept_invalid_certs_disabled() { fn insecure_accept_invalid_certs_disabled() {
// Test explicitly disabling insecure certificate acceptance // Test explicitly disabling insecure certificate acceptance
let client = HttpClient::builder() let _client = HttpClient::builder()
.insecure_accept_invalid_certs(false) .insecure_accept_invalid_certs(false)
.build(); .build();
assert!(true); // Placeholder - insecure mode disabled // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
#[test] #[test]
fn insecure_with_timeout_configuration() { fn insecure_with_timeout_configuration() {
// Test insecure mode combined with timeout configuration // Test insecure mode combined with timeout configuration
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(30)) .with_timeout(Duration::from_secs(30))
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure mode with timeout // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
@@ -52,12 +50,12 @@ fn insecure_with_headers_configuration() {
headers.insert("X-Test-Header".to_string(), "test-value".to_string()); headers.insert("X-Test-Header".to_string(), "test-value".to_string());
headers.insert("Accept".to_string(), "application/json".to_string()); headers.insert("Accept".to_string(), "application/json".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_default_headers(headers) .with_default_headers(headers)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure mode with headers // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
@@ -67,13 +65,13 @@ fn insecure_combined_configuration() {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
headers.insert("User-Agent".to_string(), "test-insecure-client".to_string()); headers.insert("User-Agent".to_string(), "test-insecure-client".to_string());
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(60)) .with_timeout(Duration::from_secs(60))
.with_default_headers(headers) .with_default_headers(headers)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure combined configuration // Test passes if compilation succeeds
} }
#[cfg(all(feature = "insecure-dangerous", feature = "rustls"))] #[cfg(all(feature = "insecure-dangerous", feature = "rustls"))]
@@ -89,12 +87,12 @@ ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExKtKjKEw91uR8gqyUZx+wW3qZjUHq3oLe+RxbEUVFWApwrKE3XxKJ CgKCAQEAuuExKtKjKEw91uR8gqyUZx+wW3qZjUHq3oLe+RxbEUVFWApwrKE3XxKJ
-----END CERTIFICATE-----"; -----END CERTIFICATE-----";
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure with rustls CA // Test passes if compilation succeeds
} }
#[cfg(all(feature = "insecure-dangerous", feature = "rustls"))] #[cfg(all(feature = "insecure-dangerous", feature = "rustls"))]
@@ -103,21 +101,21 @@ fn insecure_with_certificate_pinning() {
// Test insecure mode with certificate pinning (unusual but possible combination) // Test insecure mode with certificate pinning (unusual but possible combination)
let pins = vec![[0u8; 32]]; // Test pin let pins = vec![[0u8; 32]]; // Test pin
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_pinned_cert_sha256(pins) .with_pinned_cert_sha256(pins)
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - insecure with cert pinning // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
#[test] #[test]
fn insecure_static_convenience_method() { fn insecure_static_convenience_method() {
// Test the static convenience method for self-signed certs // Test the static convenience method for self-signed certs
let client = HttpClient::with_self_signed_certs(); let _client = HttpClient::with_self_signed_certs();
assert!(true); // Placeholder - static insecure method // Test passes if compilation succeeds
} }
#[cfg(feature = "insecure-dangerous")] #[cfg(feature = "insecure-dangerous")]
@@ -137,7 +135,7 @@ fn insecure_multiple_configurations() {
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Placeholder - multiple insecure configurations // Test passes if compilation succeeds
} }
// Test that runs only when insecure-dangerous feature is NOT enabled // Test that runs only when insecure-dangerous feature is NOT enabled
@@ -153,7 +151,7 @@ fn insecure_methods_not_available_without_feature() {
// The static method should also not be available: // The static method should also not be available:
// let _client = HttpClient::with_self_signed_certs(); // let _client = HttpClient::with_self_signed_certs();
assert!(true); // If this compiles without insecure-dangerous, the test passes // Test passes if compilation succeeds
} }
#[cfg(not(feature = "insecure-dangerous"))] #[cfg(not(feature = "insecure-dangerous"))]
@@ -166,7 +164,7 @@ fn insecure_static_method_not_available() {
let _client = HttpClient::new(); let _client = HttpClient::new();
let _client2 = HttpClient::default(); let _client2 = HttpClient::default();
assert!(true); // Safe methods are available // Test passes if compilation succeeds
} }
// Documentation test to ensure proper feature gating // Documentation test to ensure proper feature gating
@@ -189,5 +187,5 @@ fn insecure_feature_documentation_reminder() {
.insecure_accept_invalid_certs(true) .insecure_accept_invalid_certs(true)
.build(); .build();
assert!(true); // Documentation test passes // Test passes if compilation succeeds
} }

View File

@@ -3,11 +3,14 @@
//! These tests verify that the library works correctly with the rustls feature //! These tests verify that the library works correctly with the rustls feature
//! enabled, including custom CA certificate support and certificate pinning. //! enabled, including custom CA certificate support and certificate pinning.
use hyper_custom_cert::{HttpClient, HttpClientBuilder}; use hyper_custom_cert::HttpClient;
#[cfg(feature = "rustls")]
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(feature = "rustls")]
use std::time::Duration; use std::time::Duration;
// Sample PEM certificate for testing (self-signed test cert) // Sample PEM certificate for testing (self-signed test cert)
#[allow(dead_code)]
const TEST_CA_PEM: &[u8] = b"-----BEGIN CERTIFICATE----- const TEST_CA_PEM: &[u8] = b"-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
@@ -21,21 +24,19 @@ CgKCAQEAuuExKtKjKEw91uR8gqyUZx+wW3qZjUHq3oLe+RxbEUVFWApwrKE3XxKJ
#[test] #[test]
fn rustls_client_creation() { fn rustls_client_creation() {
// Test that we can create a client with rustls feature // Test that we can create a client with rustls feature
let client = HttpClient::new(); let _client = HttpClient::new();
// Basic smoke test - the client should be created successfully // Basic smoke test - the client should be created successfully
assert!(true); // Placeholder - client creation succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[test] #[test]
fn builder_with_root_ca_pem() { fn builder_with_root_ca_pem() {
// Test adding custom CA certificate via PEM bytes // Test adding custom CA certificate via PEM bytes
let client = HttpClient::builder() let _client = HttpClient::builder().with_root_ca_pem(TEST_CA_PEM).build();
.with_root_ca_pem(TEST_CA_PEM)
.build();
assert!(true); // Placeholder - CA PEM configuration succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@@ -49,7 +50,7 @@ fn builder_with_root_ca_file() {
// This demonstrates the API is available when rustls feature is enabled // This demonstrates the API is available when rustls feature is enabled
// In real usage: client = builder.with_root_ca_file("ca.pem").build(); // In real usage: client = builder.with_root_ca_file("ca.pem").build();
assert!(true); // Placeholder - CA file method availability verified // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@@ -57,21 +58,21 @@ fn builder_with_root_ca_file() {
fn builder_with_pinned_cert_sha256() { fn builder_with_pinned_cert_sha256() {
// Test certificate pinning functionality // Test certificate pinning functionality
let pins = vec![ let pins = vec![
[0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, [
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], 0x05, 0x06, 0x07, 0x08,
[0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x98, ],
0x76, 0x54, 0x32, 0x10, 0xef, 0xcd, 0xab, 0x89, [
0x67, 0x45, 0x23, 0x01, 0xff, 0xee, 0xdd, 0xcc, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xef, 0xcd,
0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44], 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
0x77, 0x66, 0x55, 0x44,
],
]; ];
let client = HttpClient::builder() let _client = HttpClient::builder().with_pinned_cert_sha256(pins).build();
.with_pinned_cert_sha256(pins)
.build();
assert!(true); // Placeholder - certificate pinning configuration succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@@ -83,31 +84,29 @@ fn builder_rustls_combined_configuration() {
let pins = vec![[0u8; 32]]; // Single test pin let pins = vec![[0u8; 32]]; // Single test pin
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_secs(60)) .with_timeout(Duration::from_secs(60))
.with_default_headers(headers) .with_default_headers(headers)
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.with_pinned_cert_sha256(pins) .with_pinned_cert_sha256(pins)
.build(); .build();
assert!(true); // Placeholder - combined rustls configuration succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[test] #[test]
fn rustls_with_multiple_ca_certificates() { fn rustls_with_multiple_ca_certificates() {
// Test adding multiple CA certificates // Test adding multiple CA certificates
let client1 = HttpClient::builder() let _client1 = HttpClient::builder().with_root_ca_pem(TEST_CA_PEM).build();
.with_root_ca_pem(TEST_CA_PEM)
.build();
// In practice, you could chain multiple with_root_ca_pem calls // In practice, you could chain multiple with_root_ca_pem calls
let client2 = HttpClient::builder() let _client2 = HttpClient::builder()
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.with_root_ca_pem(TEST_CA_PEM) // Same cert twice for testing .with_root_ca_pem(TEST_CA_PEM) // Same cert twice for testing
.build(); .build();
assert!(true); // Placeholder - multiple CA configuration succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@@ -115,12 +114,12 @@ fn rustls_with_multiple_ca_certificates() {
fn rustls_ca_file_and_pem_combination() { fn rustls_ca_file_and_pem_combination() {
// Test combining multiple PEM-based CA loading (simulating file + PEM combination) // Test combining multiple PEM-based CA loading (simulating file + PEM combination)
// For CI/CD compatibility, we use multiple PEM calls instead of file I/O // For CI/CD compatibility, we use multiple PEM calls instead of file I/O
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_root_ca_pem(TEST_CA_PEM) // Simulates file-based CA .with_root_ca_pem(TEST_CA_PEM) // Simulates file-based CA
.with_root_ca_pem(TEST_CA_PEM) // Additional PEM-based CA .with_root_ca_pem(TEST_CA_PEM) // Additional PEM-based CA
.build(); .build();
assert!(true); // Placeholder - multiple CA combination succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
@@ -129,23 +128,23 @@ fn rustls_empty_pin_list() {
// Test with empty certificate pin list // Test with empty certificate pin list
let empty_pins: Vec<[u8; 32]> = vec![]; let empty_pins: Vec<[u8; 32]> = vec![];
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_pinned_cert_sha256(empty_pins) .with_pinned_cert_sha256(empty_pins)
.build(); .build();
assert!(true); // Placeholder - empty pins configuration succeeded // Test passes if compilation succeeds
} }
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[test] #[test]
fn rustls_with_timeout_and_ca() { fn rustls_with_timeout_and_ca() {
// Test rustls-specific functionality with timeout // Test rustls-specific functionality with timeout
let client = HttpClient::builder() let _client = HttpClient::builder()
.with_timeout(Duration::from_millis(500)) .with_timeout(Duration::from_millis(500))
.with_root_ca_pem(TEST_CA_PEM) .with_root_ca_pem(TEST_CA_PEM)
.build(); .build();
assert!(true); // Placeholder - rustls with timeout succeeded // Test passes if compilation succeeds
} }
// Test that runs only when rustls feature is NOT enabled // Test that runs only when rustls feature is NOT enabled
@@ -160,5 +159,5 @@ fn rustls_methods_not_available_without_feature() {
// builder.with_root_ca_file("test.pem"); // builder.with_root_ca_file("test.pem");
// builder.with_pinned_cert_sha256(vec![[0u8; 32]]); // builder.with_pinned_cert_sha256(vec![[0u8; 32]]);
assert!(true); // If this compiles without rustls, the test passes // Test passes if compilation succeeds
} }