/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.generic;

import java.util.List;
import org.junit.Test;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.reflection.IClass;
import net.ranides.assira.reflection.mockup.MTFunction;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class TypeTokenTest {

    @Test
    public void testToken() {
        IClass<?> c1 = new TypeToken<String>(){};
        IClass<?> c2 = new TypeToken<Number>(){};
        IClass<?> c3 = new TypeToken<Object>(){};
        IClass<?> c4 = new TypeToken<List<String>>(){};
        IClass<?> c5 = new TypeToken<List<? super String>>(){};
        
        assertEquals("java.lang.String", c1.toString());
        assertEquals("java.lang.Number", c2.toString());
        assertEquals("java.lang.Object", c3.toString());
        assertEquals("java.util.List<java.lang.String>", c4.toString());
        assertEquals("java.util.List<? super java.lang.String>", c5.toString());
        
        assertEquals(String.class, c1.raw());
        assertEquals(Number.class, c2.raw());
        assertEquals(Object.class, c3.raw());
        assertEquals(List.class, c4.raw());
        assertEquals(List.class, c5.raw());
    }
    
    @Test
    public void testTokenRaw() {
        IClass<?> c1 = new TypeToken<MTFunction<String>>(){};
        IClass<?> c2 = new TypeToken<MTFunction<?>>(){};
        IClass<?> c3 = new TypeToken<MTFunction>(){};

        assertEquals("net.ranides.assira.reflection.mockup.MTFunction<java.lang.String>", c1.toString());
        assertEquals("net.ranides.assira.reflection.mockup.MTFunction<?>", c2.toString());
        assertEquals("net.ranides.assira.reflection.mockup.MTFunction<T>", c3.toString());
    }
    
    @Test
    @SuppressWarnings("unchecked")
    public void testEquals() {
        TypeToken<?> c11 = new TypeToken<String>(){};
        TypeToken<?> c12 = new TypeToken(String.class){};
        TypeToken<?> c13 = new TypeToken(IClass.typefor("Hello")){};
        TypeToken<?> c14 = new TypeToken<CharSequence>(){};
        TypeToken<?> c21 = new TypeToken<Number>(){};
        TypeToken<?> c22 = new TypeToken<Integer>(){};
        TypeToken<?> c41 = new TypeToken<List<String>>(){};
        TypeToken<?> c42 = new TypeToken<List<String>>(){};
        TypeToken<?> c43 = new TypeToken<List<CharSequence>>(){};
        TypeToken<?> c5 = new TypeToken<List<? super String>>(){};
        
        assertTrue(c11.compareTo(c12) == 0);
        assertTrue(c11.compareTo(c13) == 0);
        assertTrue(c11.compareTo(c14) > 0);
        assertTrue(c14.compareTo(c11) < 0);
        
        assertTrue(c21.compareTo(c22) < 0);
        assertTrue(c22.compareTo(c21) > 0);
        
        assertTrue(c41.equals(c42));
        assertFalse(c41.equals(c43));
        assertFalse(c41.equals(c5));
        
        assertFalse(c41.equals(new Object()));
    }
    
    @Test
    @SuppressWarnings("unchecked")
    public void testNoHash() {
        TypeToken<?> c11 = new TypeToken<String>(){};
        TypeToken<?> c12 = new TypeToken(String.class){};
        TypeToken<?> c13 = new TypeToken(IClass.typefor("Hello")){};
        TypeToken<?> c41 = new TypeToken<List<String>>(){};
        
        assertEquals(IClass.typeinfo(String.class).hashCode(), c11.hashCode());
        assertEquals(IClass.typeinfo(String.class).hashCode(), c12.hashCode());
        assertEquals(IClass.typeinfo(String.class).hashCode(), c13.hashCode());
        assertEquals(IClass.typeinfo(List.class).hashCode(), c41.hashCode());
    }
    
}
