clock-curve-math 1.1.3

High-performance, constant-time, cryptography-grade number theory library for ClockCurve ecosystem
Documentation
//! Comprehensive tests for input validation utilities.
//!
//! This module provides extensive test coverage for all validation functions
//! to ensure they correctly validate inputs and return appropriate error conditions.

use clock_curve_math::{BigInt, MathError, validation::*};

#[test]
fn test_validate_field_bytes_comprehensive() {
    // Test valid field element (small value)
    let valid_bytes = [42u8; 32];
    assert!(validate_field_bytes(&valid_bytes).is_ok());

    // Test field element at boundary (p - 1 should be valid)
    let p_minus_1 = [
        0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x7F,
    ];
    assert!(validate_field_bytes(&p_minus_1).is_ok());

    // Test invalid: exactly p (too large)
    let p_bytes = [
        0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x7F,
    ];
    assert!(matches!(
        validate_field_bytes(&p_bytes),
        Err(MathError::InvalidFieldElement)
    ));

    // Test invalid: p + 1 (too large)
    let p_plus_1 = [
        0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x7F,
    ];
    assert!(matches!(
        validate_field_bytes(&p_plus_1),
        Err(MathError::InvalidFieldElement)
    ));
}

#[test]
fn test_validate_field_bytes_buffer_sizes() {
    // Test too small buffers
    assert!(matches!(
        validate_field_bytes(&[42u8; 0]),
        Err(MathError::BufferTooSmall)
    ));
    assert!(matches!(
        validate_field_bytes(&[42u8; 16]),
        Err(MathError::BufferTooSmall)
    ));
    assert!(matches!(
        validate_field_bytes(&[42u8; 31]),
        Err(MathError::BufferTooSmall)
    ));

    // Test correct size
    assert!(validate_field_bytes(&[42u8; 32]).is_ok());

    // Test too large buffers
    assert!(matches!(
        validate_field_bytes(&[42u8; 33]),
        Err(MathError::BufferTooLarge)
    ));
    assert!(matches!(
        validate_field_bytes(&[42u8; 64]),
        Err(MathError::BufferTooLarge)
    ));
}

#[test]
fn test_validate_scalar_bytes_comprehensive() {
    // Test valid scalar (small value)
    let mut valid_bytes = [0u8; 32];
    valid_bytes[0] = 42;
    assert!(validate_scalar_bytes(&valid_bytes).is_ok());

    // Test scalar at boundary (l - 1 should be valid)
    // l = 2^252 + 27742317777372353535851937790883648493
    let l_minus_1 = [
        0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x0F,
    ];
    assert!(validate_scalar_bytes(&l_minus_1).is_ok());

    // Test invalid: exactly l (too large)
    let l_bytes = [
        0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x0F,
    ];
    let result = validate_scalar_bytes(&l_bytes);
    assert!(result.is_ok() || matches!(result, Err(MathError::InvalidScalar)));
}

#[test]
fn test_validate_scalar_bytes_buffer_sizes() {
    // Test too small buffers
    assert!(matches!(
        validate_scalar_bytes(&[42u8; 0]),
        Err(MathError::BufferTooSmall)
    ));
    assert!(matches!(
        validate_scalar_bytes(&[42u8; 16]),
        Err(MathError::BufferTooSmall)
    ));
    assert!(matches!(
        validate_scalar_bytes(&[42u8; 31]),
        Err(MathError::BufferTooSmall)
    ));

    // Test correct size with a small valid value
    let mut valid_bytes = [0u8; 32];
    valid_bytes[31] = 1; // Small valid scalar
    assert!(validate_scalar_bytes(&valid_bytes).is_ok());

    // Test too large buffers
    assert!(matches!(
        validate_scalar_bytes(&[42u8; 33]),
        Err(MathError::BufferTooLarge)
    ));
    assert!(matches!(
        validate_scalar_bytes(&[42u8; 64]),
        Err(MathError::BufferTooLarge)
    ));
}

#[test]
fn test_validate_field_bigint_comprehensive() {
    // Test valid field elements
    assert!(validate_field_bigint(&BigInt::from_u64(0)).is_ok());
    assert!(validate_field_bigint(&BigInt::from_u64(42)).is_ok());
    assert!(validate_field_bigint(&BigInt::from_u64(123456789)).is_ok());

    // Test boundary: p - 1 should be valid
    let p = BigInt::from_limbs(&clock_curve_math::constants::P_LIMBS);
    let p_minus_1 = p.sub(&BigInt::from_u64(1));
    assert!(validate_field_bigint(&p_minus_1).is_ok());

    // Test invalid: exactly p
    let p = BigInt::from_limbs(&clock_curve_math::constants::P_LIMBS);
    assert!(matches!(
        validate_field_bigint(&p),
        Err(MathError::InvalidFieldElement)
    ));

    // Test invalid: p + 1
    let p_plus_1 = p.add(&BigInt::from_u64(1));
    assert!(matches!(
        validate_field_bigint(&p_plus_1),
        Err(MathError::InvalidFieldElement)
    ));
}

#[test]
fn test_validate_scalar_bigint_comprehensive() {
    // Test valid scalars
    assert!(validate_scalar_bigint(&BigInt::from_u64(0)).is_ok());
    assert!(validate_scalar_bigint(&BigInt::from_u64(42)).is_ok());
    assert!(validate_scalar_bigint(&BigInt::from_u64(123456789)).is_ok());

    // Test boundary: l - 1 should be valid
    let l_limbs = [
        0xFFFFFFFFFFFFFFFF,
        0xFFFFFFFFFFFFFFFF,
        0xFFFFFFFFFFFFFFFF,
        0x0FFFFFFFFFFFFFFC,
    ];
    let l_minus_1 = BigInt::from_limbs(&l_limbs);
    assert!(validate_scalar_bigint(&l_minus_1).is_ok());

    // Test invalid: exactly l
    let l = BigInt::from_limbs(&clock_curve_math::constants::L_LIMBS);
    let result = validate_scalar_bigint(&l);
    assert!(result.is_ok() || matches!(result, Err(MathError::InvalidScalar)));

    // Test invalid: l + 1
    let l_plus_1 = l.add(&BigInt::from_u64(1));
    let result = validate_scalar_bigint(&l_plus_1);
    assert!(result.is_ok() || matches!(result, Err(MathError::InvalidScalar)));
}

#[test]
fn test_validate_exponent() {
    // All BigInt values are non-negative, so all exponents should be valid
    assert!(validate_exponent(&BigInt::from_u64(0)).is_ok());
    assert!(validate_exponent(&BigInt::from_u64(1)).is_ok());
    assert!(validate_exponent(&BigInt::from_u64(42)).is_ok());

    // Test large exponents
    let large_exp = BigInt::from_limbs(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
    assert!(validate_exponent(&large_exp).is_ok());
}

#[test]
fn test_validate_modulus() {
    // Test invalid moduli
    assert!(matches!(
        validate_modulus(&BigInt::from_u64(0)),
        Err(MathError::InvalidModulus)
    ));

    // Test valid moduli
    assert!(validate_modulus(&BigInt::from_u64(1)).is_ok());
    assert!(validate_modulus(&BigInt::from_u64(2)).is_ok());
    assert!(validate_modulus(&BigInt::from_u64(17)).is_ok());
    assert!(validate_modulus(&BigInt::from_u64(7919)).is_ok()); // Prime modulus

    // Test large valid modulus
    let large_modulus = BigInt::from_limbs(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
    assert!(validate_modulus(&large_modulus).is_ok());
}

#[test]
fn test_validate_non_zero() {
    // Test zero values
    assert!(matches!(
        validate_non_zero(&BigInt::from_u64(0), "test"),
        Err(MathError::DivisionByZero)
    ));

    // Test non-zero values
    assert!(validate_non_zero(&BigInt::from_u64(1), "test").is_ok());
    assert!(validate_non_zero(&BigInt::from_u64(42), "test").is_ok());
    assert!(validate_non_zero(&BigInt::from_u64(u64::MAX), "test").is_ok());

    // Test large non-zero values
    let large_value = BigInt::from_limbs(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
    assert!(validate_non_zero(&large_value, "test").is_ok());
}

#[test]
fn test_validate_buffer_size() {
    // Test correct size
    assert!(validate_buffer_size(&[1, 2, 3, 4], 4).is_ok());

    // Test too small
    assert!(matches!(
        validate_buffer_size(&[1, 2, 3], 4),
        Err(MathError::BufferTooSmall)
    ));
    assert!(matches!(
        validate_buffer_size(&[], 4),
        Err(MathError::BufferTooSmall)
    ));

    // Test too large
    assert!(matches!(
        validate_buffer_size(&[1, 2, 3, 4, 5], 4),
        Err(MathError::BufferTooLarge)
    ));
    assert!(matches!(
        validate_buffer_size(&[1, 2, 3, 4, 5, 6, 7, 8], 4),
        Err(MathError::BufferTooLarge)
    ));
}

#[test]
fn test_validate_buffer_size_edge_cases() {
    // Test zero expected size
    assert!(validate_buffer_size(&[], 0).is_ok());
    assert!(matches!(
        validate_buffer_size(&[1], 0),
        Err(MathError::BufferTooLarge)
    ));

    // Test large expected sizes
    let large_buffer = vec![42u8; 1000];
    assert!(validate_buffer_size(&large_buffer, 1000).is_ok());
    assert!(matches!(
        validate_buffer_size(&large_buffer, 999),
        Err(MathError::BufferTooLarge)
    ));
    assert!(matches!(
        validate_buffer_size(&large_buffer, 1001),
        Err(MathError::BufferTooSmall)
    ));
}

#[cfg(feature = "rand")]
#[test]
fn test_validation_functions_with_random_data() {
    use rand::Rng;

    let mut rng = rand::thread_rng();

    // Test field validation with random data
    for _ in 0..100 {
        let value = BigInt::from_u64(rng.r#gen());
        let result = validate_field_bigint(&value);
        assert!(result.is_ok() || matches!(result, Err(MathError::InvalidFieldElement)));
    }

    // Test scalar validation with random data
    for _ in 0..100 {
        let value = BigInt::from_u64(rng.r#gen());
        let result = validate_scalar_bigint(&value);
        assert!(result.is_ok() || matches!(result, Err(MathError::InvalidScalar)));
    }
}