package br.com.caelum.vraptor.interceptor; import static org.hamcrest.Matchers.hasItems; import static org.junit.Assert.assertThat; import java.util.List; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Test; import br.com.caelum.vraptor.Intercepts; public class TopologicalSortedInterceptorRegistryTest { @Intercepts static interface A extends Interceptor {} @Intercepts(before=A.class) static interface B extends Interceptor {} @Intercepts(after=A.class) static interface C extends Interceptor {} @Intercepts(after=A.class, before=C.class) static interface D extends Interceptor {} @Intercepts(before=A.class, after=C.class) static interface E extends Interceptor {} static interface F extends Interceptor {} @Test public void returnsRegisteredClasses() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class, B.class, C.class); List<Class<? extends Interceptor>> list = set.all(); assertThat(list, hasItems(A.class, B.class, C.class)); } @Test public void respectsAfterAttribute() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); set.register(C.class); assertThat(set.all(), hasRelativeOrder(A.class, C.class)); set = new TopologicalSortedInterceptorRegistry(); set.register(C.class); set.register(A.class); assertThat(set.all(), hasRelativeOrder(A.class, C.class)); } @Test public void respectsBeforeAndAfterAttribute() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); set.register(C.class); set.register(D.class); assertThat(set.all(), hasRelativeOrder(A.class, D.class, C.class)); set = new TopologicalSortedInterceptorRegistry(); set.register(C.class); set.register(D.class); set.register(A.class); assertThat(set.all(), hasRelativeOrder(A.class, D.class, C.class)); } @Test(expected=IllegalStateException.class) public void failsOnCycles() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); set.register(C.class); set.register(E.class); set.all(); } @Test public void respectsInsertionOrderIfNoRelationIsSet() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); set.register(F.class); assertThat(set.all(), hasRelativeOrder(A.class, F.class)); set = new TopologicalSortedInterceptorRegistry(); set.register(F.class); set.register(A.class); assertThat(set.all(), hasRelativeOrder(F.class, A.class)); } @Test public void usesDefaultInterceptorsIfNoRelationIsSet() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); assertThat(set.all(), hasRelativeOrder(ResourceLookupInterceptor.class, A.class, ExecuteMethodInterceptor.class)); set = new TopologicalSortedInterceptorRegistry(); set.register(F.class); assertThat(set.all(), hasRelativeOrder(ResourceLookupInterceptor.class, F.class, ExecuteMethodInterceptor.class)); } @Test public void respectsBeforeAttribute() throws Exception { TopologicalSortedInterceptorRegistry set = new TopologicalSortedInterceptorRegistry(); set.register(A.class); set.register(B.class); assertThat(set.all(), hasRelativeOrder(B.class, A.class)); set = new TopologicalSortedInterceptorRegistry(); set.register(B.class); set.register(A.class); assertThat(set.all(), hasRelativeOrder(B.class, A.class)); } private <T> Matcher<List<T>> hasRelativeOrder(final T... elements) { return new TypeSafeMatcher<List<T>>() { @Override protected void describeMismatchSafely(List<T> item, Description mismatchDescription) { } @Override protected boolean matchesSafely(List<T> item) { for (int i = 0; i < elements.length - 1; i++) { if (item.indexOf(elements[i]) > item.indexOf(elements[i+1])) { return false; } } return true; } public void describeTo(Description description) { description.appendText("A list with relative order ").appendValue(elements); } }; } }