package org.togglz.spring.web; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.http.HttpStatus; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.web.method.HandlerMethod; import org.togglz.core.Feature; import org.togglz.core.context.FeatureContext; import org.togglz.core.context.ThreadLocalFeatureManagerProvider; import org.togglz.core.manager.FeatureManager; import org.togglz.core.manager.FeatureManagerBuilder; import org.togglz.core.repository.FeatureState; import org.togglz.core.repository.mem.InMemoryStateRepository; public class FeatureInterceptorTest { private static final int METHOD_FEATURE_TWO_RESPONSE_STATUS = 302; private FeatureManager manager; private InMemoryStateRepository repository; private static enum TestFeatures implements Feature { CLASS_FEATURE, METHOD_FEATURE, METHOD_FEATURE_TWO } private static class NoEnumFeature implements Feature { @Override public String name() { return "johndoe"; }} @Before public void before() { repository = new InMemoryStateRepository(); manager = new FeatureManagerBuilder() .featureEnum(TestFeatures.class) .stateRepository(repository) .build(); ThreadLocalFeatureManagerProvider.bind(manager); } @After public void after() { ThreadLocalFeatureManagerProvider.release(); FeatureContext.clearCache(); } @FeaturesAreActive(featureClass = TestFeatures.class, features = "CLASS_FEATURE") private static class TestController { @SuppressWarnings("unused") public void classFeature() { } @FeaturesAreActive(featureClass = TestFeatures.class, features = "METHOD_FEATURE") public void methodFeature() { } @FeaturesAreActive(featureClass = TestFeatures.class, features = {"METHOD_FEATURE", "METHOD_FEATURE_TWO"}, responseStatus = METHOD_FEATURE_TWO_RESPONSE_STATUS) public void methodFeatureTwo() { } @FeaturesAreActive(featureClass = NoEnumFeature.class, features = "A") public void methodFeatureNoEnum() { } } private static class NonAnnotatedTestController { @SuppressWarnings("unused") public void doit() { } } @Test public void preHandle_noAnnotations() throws Exception { FeatureInterceptor featureInterceptor = new FeatureInterceptor(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); NonAnnotatedTestController controller = new NonAnnotatedTestController(); HandlerMethod handler = new HandlerMethod(controller, "doit"); assertEquals(true, featureInterceptor.preHandle(request, response, handler)); assertEquals(200, response.getStatus()); } @Test public void preHandle_ClassFeature_Inactive() throws Exception { assertPrehandle("classFeature", false, HttpStatus.NOT_FOUND.value()); } @Test public void preHandle_ClassFeature_Active() throws Exception { enableFeature(TestFeatures.CLASS_FEATURE); assertPrehandle("classFeature", true, HttpStatus.OK.value()); } @Test public void preHandle_MethodFeature_Inactive() throws Exception { assertPrehandle("methodFeature", false, HttpStatus.NOT_FOUND.value()); } @Test public void preHandle_MethodFeature_Active() throws Exception { enableFeature(TestFeatures.METHOD_FEATURE); assertPrehandle("methodFeature", true, HttpStatus.OK.value()); } @Test public void preHandle_MethodFeatureTwo_Inactive() throws Exception { assertPrehandle("methodFeatureTwo", false, METHOD_FEATURE_TWO_RESPONSE_STATUS); } @Test public void preHandle_MethodFeatureTwo_OnlyOneActive() throws Exception { enableFeature(TestFeatures.METHOD_FEATURE); assertPrehandle("methodFeatureTwo", false, METHOD_FEATURE_TWO_RESPONSE_STATUS); } @Test public void preHandle_MethodFeatureTwo_AllActive() throws Exception { enableFeature(TestFeatures.METHOD_FEATURE); enableFeature(TestFeatures.METHOD_FEATURE_TWO); assertPrehandle("methodFeatureTwo", true, HttpStatus.OK.value()); } @Test(expected = IllegalArgumentException.class) public void preHandle_methodFeatureNoEnum_InvalidEnum() throws Exception { assertPrehandle("methodFeatureNoEnum", false, HttpStatus.NOT_FOUND.value()); } @Test public void handlerAnnotation_OnType() throws NoSuchMethodException { TestController controller = new TestController(); HandlerMethod handler = new HandlerMethod(controller, "classFeature"); FeaturesAreActive annotation = FeatureInterceptor.handlerAnnotation(handler, FeaturesAreActive.class); assertNotNull(annotation); assertEquals(TestFeatures.class, annotation.featureClass()); assertEquals(HttpStatus.NOT_FOUND.value(), annotation.responseStatus()); assertThat(annotation.features()).containsExactly("CLASS_FEATURE"); } @Test public void handlerAnnotation_OnMethod() throws NoSuchMethodException { TestController controller = new TestController(); HandlerMethod handler = new HandlerMethod(controller, "methodFeatureTwo"); FeaturesAreActive annotation = FeatureInterceptor.handlerAnnotation(handler, FeaturesAreActive.class); assertNotNull(annotation); assertEquals(TestFeatures.class, annotation.featureClass()); assertEquals(302, annotation.responseStatus()); assertThat(annotation.features()).containsExactly("METHOD_FEATURE", "METHOD_FEATURE_TWO"); } @Test public void enumFrom() { assertEquals(TestFeatures.CLASS_FEATURE, FeatureInterceptor.enumFrom("CLASS_FEATURE", TestFeatures.class)); assertEquals(TestFeatures.METHOD_FEATURE, FeatureInterceptor.enumFrom("METHOD_FEATURE", TestFeatures.class)); assertNull(FeatureInterceptor.enumFrom("FOO", TestFeatures.class)); assertNull(FeatureInterceptor.enumFrom(null, TestFeatures.class)); } private void enableFeature(TestFeatures feature) { repository.setFeatureState(new FeatureState(feature, true)); assertTrue(manager.isActive(feature)); } private void assertPrehandle(String methodName, boolean expectedReturnValue, int expectedStatusCode) throws NoSuchMethodException, Exception { FeatureInterceptor featureInterceptor = new FeatureInterceptor(); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); TestController controller = new TestController(); HandlerMethod handler = new HandlerMethod(controller, methodName); assertEquals(expectedReturnValue, featureInterceptor.preHandle(request, response, handler)); assertEquals(expectedStatusCode, response.getStatus()); } }