package org.testory.proxy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.testory.proxy.Typing.extending;
import static org.testory.proxy.Typing.implementing;
import static org.testory.proxy.Typing.subclassing;
import static org.testory.proxy.Typing.typing;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
public class TestTyping {
private Class<?> superclass;
private Set<? extends Class<?>> interfaces;
private Typing typing;
@Before
public void before() {
superclass = Object.class;
interfaces = classes(InterfaceA.class, InterfaceB.class);
}
@Test
public void creates_legal_typing() {
assertFactory(ConcreteClass.class, interfaces);
assertFactory(AbstractClass.class, interfaces);
assertFactory(ConcreteClass.class, classes());
assertFactory(Object.class, interfaces);
}
private static void assertFactory(Class<?> superclass, Set<? extends Class<?>> interfaces) {
Typing typing = typing(superclass, interfaces);
assertEquals(superclass, typing.superclass);
assertEquals(interfaces, typing.interfaces);
}
@Test
public void fails_for_illegal_typing() {
assertFactoryFails(Interface.class, interfaces);
assertFactoryFails(AnnotationClass.class, interfaces);
assertFactoryFails(int.class, interfaces);
assertFactoryFails(Object[].class, interfaces);
assertFactoryFails(superclass, classes(ConcreteClass.class));
assertFactoryFails(superclass, classes(AbstractClass.class));
assertFactoryFails(superclass, classes(AnnotationClass.class));
assertFactoryFails(superclass, classes(int.class));
assertFactoryFails(superclass, classes(Object[].class));
assertFactoryFails(null, interfaces);
assertFactoryFails(superclass, null);
}
private static void assertFactoryFails(Class<?> superclass, Set<? extends Class<?>> interfaces) {
try {
typing(superclass, interfaces);
fail();
} catch (ProxyException e) {}
}
@Test
public void extends_type() {
typing = extending(ConcreteClass.class);
assertEquals(ConcreteClass.class, typing.superclass);
assertEquals(classes(), typing.interfaces);
}
@Test
public void implements_type() {
typing = implementing(Interface.class);
assertEquals(Object.class, typing.superclass);
assertEquals(classes(Interface.class), typing.interfaces);
}
@Test
public void implements_types() {
typing = implementing(InterfaceA.class, InterfaceB.class);
assertEquals(Object.class, typing.superclass);
assertEquals(classes(InterfaceA.class, InterfaceB.class), typing.interfaces);
}
@Test
public void subclasses_concrete_class() {
typing = subclassing(ConcreteClass.class);
assertEquals(ConcreteClass.class, typing.superclass);
assertEquals(classes(), typing.interfaces);
}
@Test
public void subclasses_abstract_class() {
typing = subclassing(AbstractClass.class);
assertEquals(AbstractClass.class, typing.superclass);
assertEquals(classes(), typing.interfaces);
}
@Test
public void subclasses_interface() {
typing = subclassing(Interface.class);
assertEquals(Object.class, typing.superclass);
assertEquals(classes(Interface.class), typing.interfaces);
}
private static Set<Class<?>> classes(Class<?>... classes) {
return new HashSet<>(Arrays.asList(classes));
}
private static class ConcreteClass {}
private static abstract class AbstractClass {}
private static interface Interface {}
private static interface InterfaceA {}
private static interface InterfaceB {}
private static @interface AnnotationClass {}
}