package net.nullschool.grains.generate;
import net.nullschool.grains.*;
import net.nullschool.reflect.*;
import org.junit.Test;
import java.beans.IntrospectionException;
import java.util.List;
import java.util.UUID;
import static org.junit.Assert.*;
import static net.nullschool.grains.generate.SymbolTable.*;
/**
* 2013-06-14<p/>
*
* @author Cameron Beccario
*/
public class SymbolTableTest {
interface Descendant<T> {
T getParent();
}
public abstract static class Organism {
public abstract int getId();
public abstract void setBob(int bob); // not a getter, so should be ignored.
public abstract String getStuff(int index); // index property, so should be ignored.
public abstract String[] getStuff(); // index property, so should be ignored.
}
public abstract static class Animal extends Organism implements Descendant<UUID> {
public abstract boolean isVertebrate();
protected abstract String getName(); // not public, so should be ignored.
}
interface RawDescendant extends Descendant {
}
@Test
public void test_collectDeclaredProperties_one_level_only() throws IntrospectionException {
List<GrainProperty> result;
result = collectDeclaredProperties(Organism.class);
assertEquals(1, result.size());
assertEquals("id", result.get(0).getName());
assertEquals(int.class, result.get(0).getType());
assertTrue(result.get(0).getFlags().isEmpty());
result = collectDeclaredProperties(Animal.class);
assertEquals(1, result.size());
assertEquals("vertebrate", result.get(0).getName());
assertEquals(boolean.class, result.get(0).getType());
assertEquals(GrainProperty.Flag.IS_PROPERTY, result.get(0).getFlags().iterator().next());
}
@Test
public void test_collectDeclaredProperties_of_generic_type() throws IntrospectionException {
List<GrainProperty> result;
// As non-parameterized class
result = collectDeclaredProperties(Descendant.class);
assertEquals(1, result.size());
assertEquals("parent", result.get(0).getName());
assertEquals(new LateTypeVariable<>("T", Descendant.class), result.get(0).getType());
assertTrue(result.get(0).getFlags().isEmpty());
// Parameterized as Descendant<String>
result = collectDeclaredProperties(new TypeToken<Descendant<String>>(){}.asType());
assertEquals(1, result.size());
assertEquals("parent", result.get(0).getName());
assertEquals(String.class, result.get(0).getType());
assertTrue(result.get(0).getFlags().isEmpty());
}
@Test
public void test_collectProperties_multiple_levels() throws IntrospectionException {
List<GrainProperty> result;
result = collectProperties(Organism.class);
assertEquals(1, result.size());
assertEquals("id", result.get(0).getName());
assertEquals(int.class, result.get(0).getType());
assertTrue(result.get(0).getFlags().isEmpty());
result = collectProperties(Animal.class);
assertEquals(3, result.size());
assertEquals("vertebrate", result.get(0).getName());
assertEquals(boolean.class, result.get(0).getType());
assertEquals(GrainProperty.Flag.IS_PROPERTY, result.get(0).getFlags().iterator().next());
assertEquals("id", result.get(1).getName());
assertEquals(int.class, result.get(1).getType());
assertTrue(result.get(1).getFlags().isEmpty());
assertEquals("parent", result.get(2).getName());
assertEquals(UUID.class, result.get(2).getType());
assertTrue(result.get(2).getFlags().isEmpty());
}
@Test
public void test_collectProperties_multiple_level_raw_generic() throws IntrospectionException {
List<GrainProperty> result;
result = collectProperties(RawDescendant.class);
assertEquals(1, result.size());
assertEquals("parent", result.get(0).getName());
assertEquals(new LateTypeVariable<>("T", Descendant.class), result.get(0).getType());
assertTrue(result.get(0).getFlags().isEmpty());
}
interface A { int getA(); } // A B
interface B { int getB(); } // \ / \
interface C extends A, B { int getC(); } // C D
interface D extends B { int getD(); } // \ /
interface E extends C, D { int getE(); } // E
@Test
public void test_collectProperties_composite_type_with_diamond() throws IntrospectionException {
List<GrainProperty> result;
result = collectProperties(C.class);
assertEquals(3, result.size());
assertEquals("c", result.get(0).getName());
assertEquals("a", result.get(1).getName());
assertEquals("b", result.get(2).getName());
result = collectProperties(E.class);
assertEquals(5, result.size());
assertEquals("e", result.get(0).getName());
assertEquals("c", result.get(1).getName());
assertEquals("d", result.get(2).getName());
assertEquals("a", result.get(3).getName());
assertEquals("b", result.get(4).getName());
}
interface P { P getX(); } // P Q
interface Q { Q getX(); } // \ /
interface R extends P, Q { R getX(); } // R
@Test
public void test_collectProperties_with_duplicate_property_names() throws IntrospectionException {
List<GrainProperty> result;
result = collectProperties(R.class);
assertEquals(3, result.size());
assertEquals(R.class, result.get(0).getType());
assertEquals(P.class, result.get(1).getType());
assertEquals(Q.class, result.get(2).getType());
}
interface T { Object getX(); } // T U V
interface U { Integer getX(); } // \ | /
interface V { Number getX(); } // \|/
interface W extends T, U, V { } // W
@Test
public void test_collectProperties_with_narrowest_type_in_upper_level() throws IntrospectionException {
List<GrainProperty> result;
result = collectProperties(W.class);
assertEquals(3, result.size());
assertEquals(Object.class, result.get(0).getType());
assertEquals(Integer.class, result.get(1).getType());
assertEquals(Number.class, result.get(2).getType());
}
@Test
public void test_resolveProperties() throws IntrospectionException {
List<GrainProperty> result;
result = resolveProperties(collectProperties(C.class));
assertEquals(3, result.size());
assertEquals("c", result.get(0).getName());
assertEquals("a", result.get(1).getName());
assertEquals("b", result.get(2).getName());
result = resolveProperties(collectProperties(R.class));
assertEquals(1, result.size());
assertEquals(R.class, result.get(0).getType());
result = resolveProperties(collectProperties(W.class));
assertEquals(1, result.size());
assertEquals(Integer.class, result.get(0).getType());
}
}