#[test]
#[cfg(feature = "coolprop")]
fn test_cache_concurrent_access() {
    let inner = CoolPropBackend::new();
    let cached = CachedBackend::new(inner);
    let fluid = FluidId::new("R134a");

    // Generate many states
    let states: Vec<_> = (0..100)
        .map(|i| {
            FluidState::from_pt(
                Pressure::from_bar(1.0 + (i as f64) * 0.1),
                Temperature::from_celsius(25.0),
            )
        })
        .collect();

    // Parallel execution via Rayon
    states.par_iter().for_each(|state| {
        // First call - populates cache
        let rho1 = cached
            .property(fluid.clone(), Property::Density, state.clone())
            .unwrap();
        // Second call - should hit cache
        let rho2 = cached
            .property(fluid.clone(), Property::Density, state.clone())
            .unwrap();

        assert_eq!(rho1, rho2);
    });
}

#[test]
#[cfg(feature = "coolprop")]
fn test_cache_quantization_hit() {
    let inner = CoolPropBackend::new();
    let cached = CachedBackend::new(inner);
    let fluid = FluidId::new("R134a");

    let p = Pressure::from_bar(10.0);
    let t = Temperature::from_kelvin(300.0);
    let state1 = FluidState::from_pt(p, t);

    // Result 1
    let rho1 = cached
        .property(fluid.clone(), Property::Density, state1)
        .unwrap();

    // State 2: very small perturbation (within 1e-10 relative)
    // Quantization is at 1e-9, so this SHOULD hit the same cache line
    let t2 = Temperature::from_kelvin(300.0 + 1e-11);
    let state2 = FluidState::from_pt(p, t2);

    // If it hits the cache, it returns EXACTLY rho1 (even if physical value changed by 1e-12)
    let rho2 = cached
        .property(fluid.clone(), Property::Density, state2)
        .unwrap();

    assert_eq!(
        rho1, rho2,
        "Cache quantization fail: small pertubations should return cached value"
    );
}

#[test]
#[cfg(feature = "coolprop")]
fn test_cache_quantization_miss() {
    let inner = CoolPropBackend::new();
    let cached = CachedBackend::new(inner);
    let fluid = FluidId::new("R134a");

    let p = Pressure::from_bar(10.0);
    let t = Temperature::from_kelvin(300.0);
    let state1 = FluidState::from_pt(p, t);

    let rho1 = cached
        .property(fluid.clone(), Property::Density, state1)
        .unwrap();

    // Large perturbation (1e-6) - should be a cache miss and calculate new value
    let t2 = Temperature::from_kelvin(300.0 + 1e-6);
    let state2 = FluidState::from_pt(p, t2);

    let rho2 = cached
        .property(fluid.clone(), Property::Density, state2)
        .unwrap();

    // Value should be slightly different, not identical to cached one
    assert_ne!(rho1, rho2);
    assert_relative_eq!(rho1, rho2, max_relative = 1e-4);
}
