diff --git a/web/src/test/groovy/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.groovy b/web/src/test/groovy/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.groovy new file mode 100644 index 0000000000..05b91d32d5 --- /dev/null +++ b/web/src/test/groovy/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.groovy @@ -0,0 +1,263 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.web.context; + +import java.util.EnumSet; + +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; + +import org.springframework.security.web.session.HttpSessionEventPublisher; +import org.springframework.web.filter.DelegatingFilterProxy; + +import spock.lang.Specification + +/** + * @author Rob Winch + * + */ +class AbstractSecurityWebApplicationInitializerTests extends Specification { + + def defaults() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){}.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 1 * registration.setAsyncSupported(true) + 0 * context.addListener(_) + } + + def "enableHttpSessionEventPublisher() = true"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected boolean enableHttpSessionEventPublisher() { + return true; + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 1 * registration.setAsyncSupported(true) + 1 * context.addListener(HttpSessionEventPublisher) + } + + def "custom getSecurityDispatcherTypes()"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected EnumSet getSecurityDispatcherTypes() { + return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.FORWARD); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.FORWARD), false, "/*"); + 1 * registration.setAsyncSupported(true) + 0 * context.addListener(_) + } + + def "custom getDispatcherWebApplicationContextSuffix"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected String getDispatcherWebApplicationContextSuffix() { + return "dispatcher" + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == "org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 1 * registration.setAsyncSupported(true) + 0 * context.addListener(_) + } + + def "springSecurityFilterChain already registered"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){}.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> null + IllegalStateException success = thrown() + success.message == "Duplicate Filter registration for 'springSecurityFilterChain'. Check to ensure the Filter is only configured once." + } + + def "insertFilters"() { + setup: + Filter filter1 = Mock() + Filter filter2 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + insertFilters(context, filter1, filter2); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 3 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 3 * registration.setAsyncSupported(true) + 0 * context.addListener(_) + 1 * context.addFilter(_, filter1) >> registration + 1 * context.addFilter(_, filter2) >> registration + } + + def "insertFilters already registered"() { + setup: + Filter filter1 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + insertFilters(context, filter1); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 1 * context.addFilter(_, filter1) >> null + IllegalStateException success = thrown() + success.message == "Duplicate Filter registration for 'filter'. Check to ensure the Filter is only configured once." + } + + def "insertFilters no filters"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + insertFilters(context); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + IllegalArgumentException success = thrown() + success.message == "filters cannot be null or empty" + } + + def "insertFilters filters with null"() { + setup: + Filter filter1 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + insertFilters(context, filter1, null); + } + }.onStartup(context) + then: + 2 * context.addFilter(_, _) >> registration + IllegalArgumentException success = thrown() + success.message == "filters cannot contain null values. Got [Mock for type 'Filter' named 'filter1', null]" + } + + def "appendFilters"() { + setup: + Filter filter1 = Mock() + Filter filter2 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + appendFilters(context,filter1, filter2); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 2 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), true, "/*"); + 3 * registration.setAsyncSupported(true) + 0 * context.addListener(_) + 1 * context.addFilter(_, filter1) >> registration + 1 * context.addFilter(_, filter2) >> registration + } + + def "appendFilters already registered"() { + setup: + Filter filter1 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + appendFilters(context, filter1); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + 1 * registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*"); + 1 * context.addFilter(_, filter1) >> null + IllegalStateException success = thrown() + success.message == "Duplicate Filter registration for 'filter'. Check to ensure the Filter is only configured once." + } + + def "appendFilters no filters"() { + setup: + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + appendFilters(context); + } + }.onStartup(context) + then: + 1 * context.addFilter("springSecurityFilterChain", {DelegatingFilterProxy f -> f.targetBeanName == "springSecurityFilterChain" && f.contextAttribute == null}) >> registration + IllegalArgumentException success = thrown() + success.message == "filters cannot be null or empty" + } + + def "appendFilters filters with null"() { + setup: + Filter filter1 = Mock() + ServletContext context = Mock() + FilterRegistration.Dynamic registration = Mock() + when: + new AbstractSecurityWebApplicationInitializer(){ + protected void afterSpringSecurityFilterChain(ServletContext servletContext) { + appendFilters(context, filter1, null); + } + }.onStartup(context) + then: + 2 * context.addFilter(_, _) >> registration + IllegalArgumentException success = thrown() + success.message == "filters cannot contain null values. Got [Mock for type 'Filter' named 'filter1', null]" + } + + def "DEFAULT_FILTER_NAME == springSecurityFilterChain"() { + expect: + AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME == "springSecurityFilterChain" + } +} diff --git a/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTest.java b/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTest.java deleted file mode 100644 index 006de03917..0000000000 --- a/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.springframework.security.web.context; - - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Keesun Baik - */ -public class AbstractSecurityWebApplicationInitializerTest { - - @Test - public void defaultFilterName() { - assertEquals(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, "springSecurityFilterChain"); - } - -} diff --git a/web/web.gradle b/web/web.gradle index 19e9ec6f35..69014574a6 100644 --- a/web/web.gradle +++ b/web/web.gradle @@ -1,4 +1,8 @@ +apply plugin: 'groovy' + dependencies { + groovy 'org.codehaus.groovy:groovy:1.8.7' + compile project(':spring-security-core'), 'aopalliance:aopalliance:1.0', "org.springframework:spring-aop:$springVersion", @@ -14,6 +18,7 @@ dependencies { testCompile project(':spring-security-core').sourceSets.test.output, 'commons-codec:commons-codec:1.3', "org.slf4j:jcl-over-slf4j:$slf4jVersion", + 'org.spockframework:spock-core:0.6-groovy-1.8', "org.springframework:spring-test:$springVersion", powerMockDependencies