//! Regression tests for the Value Hash/Eq contract and integer formatting.

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use immutability_helper::{stringifiable, Value};

fn hash_of(value: &Value) -> u64 {
    let mut hasher = DefaultHasher::new();
    value.hash(&mut hasher);
    hasher.finish()
}

#[test]
fn equal_containers_hash_equally_regardless_of_order() {
    let object_a = Value::object(vec![("a", Value::from(1)), ("b", Value::from(2))]);
    let object_b = Value::object(vec![("b", Value::from(2)), ("a", Value::from(1))]);
    assert_eq!(object_a, object_b);
    assert_eq!(hash_of(&object_a), hash_of(&object_b));

    let map_a = Value::map(vec![
        (Value::from("a"), Value::from(1)),
        (Value::from("b"), Value::from(2)),
    ]);
    let map_b = Value::map(vec![
        (Value::from("b"), Value::from(2)),
        (Value::from("a"), Value::from(1)),
    ]);
    assert_eq!(map_a, map_b);
    assert_eq!(hash_of(&map_a), hash_of(&map_b));

    let set_a = Value::set([Value::from(1), Value::from(2)]);
    let set_b = Value::set([Value::from(2), Value::from(1)]);
    assert_eq!(set_a, set_b);
    assert_eq!(hash_of(&set_a), hash_of(&set_b));
}

#[test]
fn large_integers_format_without_i64_saturation() {
    assert_eq!(stringifiable(&Value::Number(1e20)), "100000000000000000000");
    // Small integers and signed zero keep their existing rendering.
    assert_eq!(stringifiable(&Value::Number(7.0)), "7");
    assert_eq!(stringifiable(&Value::Number(-0.0)), "0");
}
