// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

extern crate test;
use self::test::Bencher;
use unify::{UnifyKey, UnificationTable};

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct UnitKey(u32);

impl UnifyKey for UnitKey {
    type Value = ();
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> UnitKey { UnitKey(u) }
    fn tag(_: Option<UnitKey>) -> &'static str { "UnitKey" }
}

#[test]
fn basic() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let k1 = ut.new_key(());
    let k2 = ut.new_key(());
    assert_eq!(ut.unioned(k1, k2), false);
    ut.union(k1, k2);
    assert_eq!(ut.unioned(k1, k2), true);
}

#[test]
fn big_array() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }

    for i in 1..MAX {
        let l = keys[i-1];
        let r = keys[i];
        ut.union(l, r);
    }

    for i in 0..MAX {
        assert!(ut.unioned(keys[0], keys[i]));
    }
}

#[bench]
fn big_array_bench(b: &mut Bencher) {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }


    b.iter(|| {
        for i in 1..MAX {
            let l = keys[i-1];
            let r = keys[i];
            ut.union(l, r);
        }

        for i in 0..MAX {
            assert!(ut.unioned(keys[0], keys[i]));
        }
    })
}

#[test]
fn even_odd() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 10;

    for i in 0..MAX {
        let key = ut.new_key(());
        keys.push(key);

        if i >= 2 {
            ut.union(key, keys[i-2]);
        }
    }

    for i in 1..MAX {
        assert!(!ut.unioned(keys[i-1], keys[i]));
    }

    for i in 2..MAX {
        assert!(ut.unioned(keys[i-2], keys[i]));
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct IntKey(u32);

impl UnifyKey for IntKey {
    type Value = Option<i32>;
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> IntKey { IntKey(u) }
    fn tag(_: Option<IntKey>) -> &'static str { "IntKey" }
}

/// Test unifying a key whose value is `Some(_)`  with a key whose value is `None`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_Some_key_None() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `None`  with a key whose value is `Some(_)`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_None_key_Some() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k2, k1).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(y)`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_key_Some_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(23));
    assert_eq!(ut.unify_var_var(k1, k2), Err((22, 23)));
    assert_eq!(ut.unify_var_var(k2, k1), Err((23, 22)));
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(23));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(x)`.
/// This should be ok.
#[test]
fn unify_key_Some_x_key_Some_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(22));
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(22));
}

/// Test unifying a key whose value is `None` with a value is `x`.
/// Afterwards key should be `x`.
#[test]
fn unify_key_None_val() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(None);
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `y`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_val_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert_eq!(ut.unify_var_value(k1, 23), Err((22, 23)));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `x`.
/// This should be ok.
#[test]
fn unify_key_Some_x_val_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

