clock-curve-math 1.1.3

High-performance, constant-time, cryptography-grade number theory library for ClockCurve ecosystem
Documentation
//! Cross-platform compatibility tests for clock-curve-math
//!
//! These tests ensure the library works correctly across different platforms,
//! architectures, and feature configurations.
//!
//! This module tests the library's functionality across different platforms,
//! architectures, and feature configurations.
//!
//! The tests are designed to cover the library's core functionality, including:
//! - Basic arithmetic operations
//! - Constant-time operations
//! - Serialization/deserialization
//! - Montgomery arithmetic
//! - BigInt operations
#[cfg(test)]
mod tests {
    use clock_curve_math::*;

    /// Test basic functionality across all configurations
    #[test]
    fn test_basic_arithmetic() {
        // Test FieldElement basic operations
        let a = FieldElement::from_u64(10);
        let b = FieldElement::from_u64(20);
        let sum = a.add(&b);
        let product = a.mul(&b);

        assert_eq!(sum.to_bytes()[0..8], [30, 0, 0, 0, 0, 0, 0, 0][..]);
        assert_eq!(product.to_bytes()[0..8], [200, 0, 0, 0, 0, 0, 0, 0][..]);

        // Test Scalar basic operations
        let s1 = Scalar::from_u64(5);
        let s2 = Scalar::from_u64(7);
        let s_sum = s1.add(&s2);
        let s_product = s1.mul(&s2);

        assert_eq!(s_sum.to_bytes()[0..8], [12, 0, 0, 0, 0, 0, 0, 0][..]);
        assert_eq!(s_product.to_bytes()[0..8], [35, 0, 0, 0, 0, 0, 0, 0][..]);
    }

    /// Test constant-time operations
    #[test]
    fn test_constant_time_operations() {
        let a = FieldElement::from_u64(42);
        let b = FieldElement::from_u64(24);

        // Test comparison operations on bytes
        let a_bytes = a.to_bytes();
        let b_bytes = b.to_bytes();
        assert!(ct_eq(a_bytes[0] as u64, a_bytes[0] as u64) != 0);
        assert!(ct_eq(a_bytes[0] as u64, b_bytes[0] as u64) == 0);

        // Test conditional operations on field elements
        let selected = FieldElement::conditional_select(&a, &b, ct::Choice::from_bool(true));
        assert_eq!(selected, a);

        let selected = FieldElement::conditional_select(&a, &b, ct::Choice::from_bool(false));
        assert_eq!(selected, b);
    }

    /// Test serialization/deserialization
    #[test]
    fn test_serialization() {
        let original = FieldElement::from_u64(12345);
        let bytes = original.to_bytes();
        let restored = FieldElement::from_bytes(&bytes).unwrap();

        assert_eq!(original, restored);

        let scalar_original = Scalar::from_u64(67890);
        let scalar_bytes = scalar_original.to_bytes();
        let scalar_restored = Scalar::from_bytes(&scalar_bytes).unwrap();

        assert_eq!(scalar_original, scalar_restored);
    }

    /// Test Montgomery arithmetic
    #[test]
    fn test_montgomery_arithmetic() {
        let a = FieldElement::from_u64(100);
        let b = FieldElement::from_u64(200);

        // Test that field multiplication works (which uses Montgomery internally)
        let product = a.mul(&b);

        // Create expected result manually: 100 * 200 = 20000
        let expected = FieldElement::from_u64(20000);
        assert_eq!(product, expected);
    }

    /// Test BigInt operations (when available)
    #[cfg(any(feature = "bigint-backend", feature = "alloc"))]
    #[test]
    fn test_bigint_operations() {
        let a = BigInt::from_u64(1000);
        let b = BigInt::from_u64(2000);

        let sum = a.add(&b);
        let product = a.mul(&b);

        // Convert to field elements to check the results
        let sum_field = FieldElement::from_bigint(&sum).unwrap();
        let product_field = FieldElement::from_bigint(&product).unwrap();

        assert_eq!(sum_field, FieldElement::from_u64(3000));
        assert_eq!(product_field, FieldElement::from_u64(2000000));
    }

    /// Test validation functions
    #[test]
    fn test_validation() {
        // All-zero bytes are valid for both field and scalar
        let valid_field_bytes = [0u8; 32];
        let valid_scalar_bytes = [0u8; 32];

        assert!(validate_field_bytes(&valid_field_bytes).is_ok());
        assert!(validate_scalar_bytes(&valid_scalar_bytes).is_ok());

        // Test invalid sizes
        let invalid_bytes = [0u8; 16];
        assert!(validate_field_bytes(&invalid_bytes).is_err());
        assert!(validate_scalar_bytes(&invalid_bytes).is_err());
    }

    /// Test edge cases
    #[test]
    fn test_edge_cases() {
        // Test zero
        let zero_field = FieldElement::from_u64(0);
        let zero_scalar = Scalar::from_u64(0);

        // Test that zero behaves correctly in operations
        let x = FieldElement::from_u64(42);
        assert_eq!(zero_field.add(&x), x); // 0 + x = x

        let s = Scalar::from_u64(42);
        assert_eq!(zero_scalar.add(&s), s); // 0 + s = s

        // Test one
        let one_field = FieldElement::from_u64(1);
        let one_scalar = Scalar::from_u64(1);

        // Test that 1 * x = x
        assert_eq!(one_field.mul(&x), x);

        assert_eq!(one_scalar.mul(&s), s);

        // Test field modular reduction
        let large_value = FieldElement::from_u64(u64::MAX);
        let doubled = large_value.add(&large_value);
        // Should not panic and should produce valid field element
        let _ = doubled.to_bytes();
    }

    /// Test that operations don't panic with edge inputs
    #[test]
    fn test_no_panics() {
        // Test with all-zero bytes (should be valid)
        let zero_bytes = [0u8; 32];
        let _ = FieldElement::from_bytes(&zero_bytes).unwrap();
        let _ = Scalar::from_bytes(&zero_bytes).unwrap();

        // Test with small valid values
        let small_bytes = [1u8; 32];
        let _ = FieldElement::from_bytes(&small_bytes).unwrap();
        let _ = Scalar::from_bytes(&small_bytes).unwrap();

        // Test arithmetic with these edge cases
        let field_zero = FieldElement::from_bytes(&zero_bytes).unwrap();
        let field_small = FieldElement::from_bytes(&small_bytes).unwrap();
        let scalar_zero = Scalar::from_bytes(&zero_bytes).unwrap();
        let scalar_small = Scalar::from_bytes(&small_bytes).unwrap();

        // These should not panic
        let _ = field_zero.add(&field_small);
        let _ = field_zero.mul(&field_small);
        let _ = scalar_zero.add(&scalar_small);
        let _ = scalar_zero.mul(&scalar_small);
    }
}