//! Constant-time verification tests.
//!
//! Tests to verify that operations execute in constant time
//! regardless of input values.

use clock_bigint::{BigInt, add, ct};

#[test]
fn test_ct_select() {
    // Constant-time select should not branch on choice value
    let a = 10u64;
    let b = 20u64;

    let result0 = ct::ct_select_u64(0, a, b);
    let result1 = ct::ct_select_u64(1, a, b);

    assert_eq!(result0, b);
    assert_eq!(result1, a);
}

#[test]
fn test_ct_comparisons() {
    // Constant-time comparisons should work correctly
    assert_eq!(ct::ct_lt(5, 10), 1);
    assert_eq!(ct::ct_lt(10, 5), 0);
    assert_eq!(ct::ct_lt(10, 10), 0);

    assert_eq!(ct::ct_eq(5, 5), 1);
    assert_eq!(ct::ct_eq(5, 10), 0);

    assert_eq!(ct::ct_gt(10, 5), 1);
    assert_eq!(ct::ct_gt(5, 10), 0);
}

#[test]
fn test_arithmetic_constant_time_properties() {
    // Operations should execute full loops regardless of value
    // This is a basic test - full constant-time verification would
    // require timing analysis

    let small = BigInt::from_u64(1, 10);
    let large = BigInt::from_u64(u64::MAX, 10);

    // These should both execute the same number of operations
    // (for same limb count)
    let _sum1 = add(&small, &small);
    let _sum2 = add(&large, &large);

    // If both succeed, constant-time properties are maintained
    // (at least at the algorithm level)
}

#[test]
fn test_ct_swap() {
    let mut a = 10u64;
    let mut b = 20u64;

    ct::ct_swap(0, &mut a, &mut b);
    assert_eq!(a, 10);
    assert_eq!(b, 20);

    let mut a = 10u64;
    let mut b = 20u64;
    ct::ct_swap(1, &mut a, &mut b);
    assert_eq!(a, 20);
    assert_eq!(b, 10);
}

// Note: Full constant-time verification would require:
// - Statistical timing analysis
// - Power analysis
// - Cache timing analysis
// These are beyond the scope of unit tests and require specialized tools.
