clock-hash 1.0.0

ClockHash-256: Consensus hash function for ClockinChain
Documentation
//! API completeness tests for ClockHash-256
//!
//! Tests to ensure all public APIs are properly exposed and functional.

use clock_hash::*;

/// Test that all main functions are accessible and work
#[test]
fn test_main_functions_accessible() {
    let data = b"api completeness test";

    // Test clockhash256
    let hash1 = clockhash256(data);
    assert_eq!(hash1.len(), 32);

    // Test clockhash256_domain
    let hash2 = clockhash256_domain(b"DOMAIN", data);
    assert_eq!(hash2.len(), 32);
    assert_ne!(hash1, hash2);

    // Test clockhash256_with_domain
    let hash3 = clockhash256_with_domain(DomainTag::Block, data);
    assert_eq!(hash3.len(), 32);
    assert_ne!(hash1, hash3);

    // Test ClockHasher
    let mut hasher = ClockHasher::new();
    hasher.update(data);
    let hash4 = hasher.finalize();
    assert_eq!(hash4.len(), 32);
    assert_eq!(hash1, hash4); // Should match one-shot
}

/// Test that all constants are accessible
#[test]
fn test_constants_accessible() {
    // Test IV accessibility
    assert_eq!(constants::IV.len(), 8);
    for &word in &constants::IV {
        assert!(word != 0); // IV should not be all zeros
    }

    // Test rotation schedule
    assert_eq!(constants::ROTATION_SCHEDULE.len(), 16);

    // Test primes
    assert!(constants::P0 != 0);
    assert!(constants::P1 != 0);

    // Test S-box
    assert_eq!(constants::SBOX.len(), 256);
}

/// Test that all domain tags are accessible
#[test]
fn test_domain_tags_accessible() {
    use clock_hash::tags;

    // Test all predefined tags
    let _block_tag = tags::CLK_BLOCK;
    let _tx_tag = tags::CLK_TX;
    let _merkle_tag = tags::CLK_MERKLE;
    let _nonce_tag = tags::CLK_NONCE;
    let _rng_tag = tags::CLK_RNG;

    // Test they are not empty
    assert!(!tags::CLK_BLOCK.is_empty());
    assert!(!tags::CLK_TX.is_empty());
    assert!(!tags::CLK_MERKLE.is_empty());
    assert!(!tags::CLK_NONCE.is_empty());
    assert!(!tags::CLK_RNG.is_empty());
}

/// Test that utility functions are accessible
#[test]
fn test_utils_accessible() {
    use clock_hash::utils;

    // Test rotation functions
    assert_eq!(utils::rotl64(0x1234567890ABCDEF, 8), 0x34567890ABCDEF12);
    assert_eq!(utils::rotr64(0x1234567890ABCDEF, 8), 0xEF1234567890ABCD);
    assert_eq!(utils::rotl8(0x12, 4), 0x21);
}

/// Test that CPU ID functions are accessible (when available)
#[test]
fn test_cpuid_accessible() {
    // These functions should not panic
    let _vendor = cpuid::get_vendor();
    let _family_model_stepping = cpuid::get_family_model_stepping();

    // Test AVX detection (may return false on some systems)
    let _has_avx = cpuid::has_avx();
    let _has_avx2 = cpuid::has_avx2();
}

/// Test that security verification functions are accessible via re-export
#[test]
fn test_security_functions_accessible() {
    // Test the re-exported security functions
    let input1 = [0u8; 64];
    let input2 = [0u8; 64]; // Different from input1

    // Test avalanche verification (re-exported)
    let avalanche = verify_avalanche(&input1, &input2);
    assert!(avalanche >= 0.0 && avalanche <= 1.0);

    // Test collision resistance (re-exported)
    let test_cases: &[&[u8]] = &[&b"test1"[..], &b"test2"[..], &b"test3"[..]];
    let no_collisions = verify_collision_resistance(test_cases);
    assert!(no_collisions);

    // Test domain separation (re-exported)
    let domains: &[&[u8]] = &[&b"domain1"[..], &b"domain2"[..]];
    let domains_separated = verify_domain_separation(b"data", domains);
    assert!(domains_separated);
}

/// Test that performance functions are accessible (when std is available)
#[cfg(feature = "std")]
#[test]
fn test_performance_functions_accessible() {
    // Test the re-exported performance functions
    let throughput = measure_throughput(100, 1024);
    assert!(throughput > 0.0);

    let stats = performance_stats();
    assert!(stats.len() > 0);

    let benchmarks = benchmark_sizes();
    assert!(benchmarks.len() > 0);
}

/// Test that all SIMD functions are accessible (when SIMD feature is enabled)
#[cfg(feature = "simd")]
#[test]
fn test_simd_functions_accessible() {
    use clock_hash::simd::dispatch::{is_avx2_available, is_avx512_available};

    // Test CPU feature detection
    let _avx2_available = is_avx2_available();
    let _avx512_available = is_avx512_available();

    // Test SIMD dispatch (these should not panic)
    let mut data = [0u64; 16];
    unsafe {
        // Note: These are unsafe functions, but they should not crash
        // We can't easily test their correctness without more setup
        let _ = std::panic::catch_unwind(|| {
            simd::clock_mix_avx2(&mut data);
        });
    }
}

/// Test that all public types implement expected traits
#[test]
fn test_public_types_traits() {
    // Test that ClockHasher implements Default
    let _hasher1 = ClockHasher::new();
    let _hasher2 = ClockHasher::default();

    // Test that DomainTag implements expected traits
    let tag1 = DomainTag::Block;
    let tag2 = DomainTag::Transaction;
    assert!(tag1 == tag1);
    assert!(tag1 != tag2);

    // Test that as_bytes works
    let bytes = tag1.as_bytes();
    assert!(!bytes.is_empty());
}