SEC-2077: Concurrency support

Provide abstractions for transferring a SecurityContext across threads.

The main concepts are the DelegatingSecurityContextCallable and the
DelegatingSecurityContextRunnable which contain a SecurityContext to establish before
delegating to a Callable or Runnable.

There are also wrapper implementations for each of the key java.util.concurrent and
spring task interfaces to make using the DelegatingSecurityContextCallable and
DelegatingSecurityContextRunnable transparent to users. For example a
DelegatingSecurityContextTaskExecutor which can be injected with a specific
SecurityContext or use the SecurityContext from the SecurityContextHolder at the time the
task is submitted. There are similar  implementations for each of the key
java.util.concurrent and spring task interfaces.

Note that in order to get DelegatingSecurityContextExecutorService to compile with
JDK 5 or JDK 6 we could not use type safe methods. See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6267833 for details.
This commit is contained in:
Rob Winch
2012-11-08 22:20:01 -06:00
parent 30780baf24
commit 51fd83060e
31 changed files with 1917 additions and 1 deletions

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
/**
* Abstract class for testing {@link DelegatingSecurityContextExecutorService} which allows customization of
* how {@link DelegatingSecurityContextExecutorService} and its mocks are created.
*
* @author Rob Winch
* @since 3.2
* @see CurrentDelegatingSecurityContextExecutorServiceTests
* @see ExplicitDelegatingSecurityContextExecutorServiceTests
*/
public abstract class AbstractDelegatingSecurityContextExecutorServiceTests extends AbstractDelegatingSecurityContextExecutorTests {
@Mock
private Future<Object> expectedFutureObject;
@Mock
private Object resultArg;
protected DelegatingSecurityContextExecutorService executor;
@Before
public final void setUpExecutorService() {
executor = create();
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegate() {
new DelegatingSecurityContextExecutorService(null);
}
@Test
public void shutdown() {
executor.shutdown();
verify(delegate).shutdown();
}
@Test
public void shutdownNow() {
List<Runnable> result = executor.shutdownNow();
verify(delegate).shutdownNow();
assertThat(result).isEqualTo(delegate.shutdownNow()).isNotNull();
}
@Test
public void isShutdown() {
boolean result = executor.isShutdown();
verify(delegate).isShutdown();
assertThat(result).isEqualTo(delegate.isShutdown()).isNotNull();
}
@Test
public void isTerminated() {
boolean result = executor.isTerminated();
verify(delegate).isTerminated();
assertThat(result).isEqualTo(delegate.isTerminated()).isNotNull();
}
@Test
public void awaitTermination() throws InterruptedException {
boolean result = executor.awaitTermination(1, TimeUnit.SECONDS);
verify(delegate).awaitTermination(1, TimeUnit.SECONDS);
assertThat(result).isEqualTo(delegate.awaitTermination(1, TimeUnit.SECONDS)).isNotNull();
}
@Test
public void submitCallable() throws Exception {
when(delegate.submit(wrappedCallable)).thenReturn(expectedFutureObject);
Future<Object> result = executor.submit(callable);
verify(delegate).submit(wrappedCallable);
assertThat(result).isEqualTo(expectedFutureObject);
}
@Test
public void submitRunnableWithResult() throws Exception {
when(delegate.submit(wrappedRunnable, resultArg)).thenReturn(expectedFutureObject);
Future<Object> result = executor.submit(runnable, resultArg);
verify(delegate).submit(wrappedRunnable, resultArg);
assertThat(result).isEqualTo(expectedFutureObject);
}
@Test
@SuppressWarnings("unchecked")
public void submitRunnable() throws Exception {
when((Future<Object>)delegate.submit(wrappedRunnable)).thenReturn(expectedFutureObject);
Future<?> result = executor.submit(runnable);
verify(delegate).submit(wrappedRunnable);
assertThat(result).isEqualTo(expectedFutureObject);
}
@Test
@SuppressWarnings("unchecked")
public void invokeAll() throws Exception {
List<Future<Object>> exectedResult = Arrays.asList(expectedFutureObject);
List<Callable<Object>> wrappedCallables = Arrays.asList(wrappedCallable);
when(delegate.invokeAll(wrappedCallables)).thenReturn(exectedResult);
List<Future<Object>> result = executor.invokeAll(Arrays.asList(callable));
verify(delegate).invokeAll(wrappedCallables);
assertThat(result).isEqualTo(exectedResult);
}
@Test
@SuppressWarnings("unchecked")
public void invokeAllTimeout() throws Exception {
List<Future<Object>> exectedResult = Arrays.asList(expectedFutureObject);
List<Callable<Object>> wrappedCallables = Arrays.asList(wrappedCallable);
when(delegate.invokeAll(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn(exectedResult);
List<Future<Object>> result = executor.invokeAll(Arrays.asList(callable), 1, TimeUnit.SECONDS);
verify(delegate).invokeAll(wrappedCallables, 1, TimeUnit.SECONDS);
assertThat(result).isEqualTo(exectedResult);
}
@Test
@SuppressWarnings("unchecked")
public void invokeAny() throws Exception {
List<Future<Object>> exectedResult = Arrays.asList(expectedFutureObject);
List<Callable<Object>> wrappedCallables = Arrays.asList(wrappedCallable);
when(delegate.invokeAny(wrappedCallables)).thenReturn(exectedResult);
Object result = executor.invokeAny(Arrays.asList(callable));
verify(delegate).invokeAny(wrappedCallables);
assertThat(result).isEqualTo(exectedResult);
}
@Test
@SuppressWarnings("unchecked")
public void invokeAnyTimeout() throws Exception {
List<Future<Object>> exectedResult = Arrays.asList(expectedFutureObject);
List<Callable<Object>> wrappedCallables = Arrays.asList(wrappedCallable);
when(delegate.invokeAny(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn(exectedResult);
Object result = executor.invokeAny(Arrays.asList(callable), 1, TimeUnit.SECONDS);
verify(delegate).invokeAny(wrappedCallables, 1, TimeUnit.SECONDS);
assertThat(result).isEqualTo(exectedResult);
}
protected abstract DelegatingSecurityContextExecutorService create();
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.mockito.Mockito.verify;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import org.junit.Test;
import org.mockito.Mock;
/**
* Abstract class for testing {@link DelegatingSecurityContextExecutor} which allows customization of
* how {@link DelegatingSecurityContextExecutor} and its mocks are created.
*
* @author Rob Winch
* @since 3.2
* @see CurrentDelegatingSecurityContextExecutorTests
* @see ExplicitDelegatingSecurityContextExecutorTests
*/
public abstract class AbstractDelegatingSecurityContextExecutorTests extends AbstractDelegatingSecurityContextTestSupport {
@Mock
protected ScheduledExecutorService delegate;
private DelegatingSecurityContextExecutor executor;
// --- constructor ---
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegate() {
new DelegatingSecurityContextExecutor(null);
}
// --- execute ---
@Test
public void execute() {
executor = create();
executor.execute(runnable);
verify(getExecutor()).execute(wrappedRunnable);
}
protected Executor getExecutor() {
return delegate;
}
protected abstract DelegatingSecurityContextExecutor create();
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
/**
* Abstract class for testing {@link DelegatingSecurityContextScheduledExecutorService} which allows customization of
* how {@link DelegatingSecurityContextScheduledExecutorService} and its mocks are created.
*
* @author Rob Winch
* @since 3.2
* @see CurrentDelegatingSecurityContextScheduledExecutorServiceTests
* @see ExplicitDelegatingSecurityContextScheduledExecutorServiceTests
*/
public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceTests extends
AbstractDelegatingSecurityContextExecutorServiceTests {
@Mock
private ScheduledFuture<Object> expectedResult;
private DelegatingSecurityContextScheduledExecutorService executor;
@Before
public final void setUpExecutor() {
executor = create();
}
@Test
@SuppressWarnings("unchecked")
public void scheduleRunnable() {
when((ScheduledFuture<Object>)delegate.schedule(wrappedRunnable, 1, TimeUnit.SECONDS)).thenReturn(expectedResult);
ScheduledFuture<?> result = executor.schedule(runnable, 1, TimeUnit.SECONDS);
assertThat(result).isEqualTo(expectedResult);
verify(delegate).schedule(wrappedRunnable, 1, TimeUnit.SECONDS);
}
@Test
public void scheduleCallable() {
when((ScheduledFuture<Object>)delegate.schedule(wrappedCallable, 1, TimeUnit.SECONDS)).thenReturn(expectedResult);
ScheduledFuture<Object> result = executor.schedule(callable, 1, TimeUnit.SECONDS);
assertThat(result).isEqualTo(expectedResult);
verify(delegate).schedule(wrappedCallable, 1, TimeUnit.SECONDS);
}
@Test
@SuppressWarnings("unchecked")
public void scheduleAtFixedRate() {
when((ScheduledFuture<Object>)delegate.scheduleAtFixedRate(wrappedRunnable, 1, 2, TimeUnit.SECONDS)).thenReturn(expectedResult);
ScheduledFuture<?> result = executor.scheduleAtFixedRate(runnable, 1, 2, TimeUnit.SECONDS);
assertThat(result).isEqualTo(expectedResult);
verify(delegate).scheduleAtFixedRate(wrappedRunnable, 1, 2, TimeUnit.SECONDS);
}
@Test
@SuppressWarnings("unchecked")
public void scheduleWithFixedDelay() {
when((ScheduledFuture<Object>)delegate.scheduleWithFixedDelay(wrappedRunnable, 1, 2, TimeUnit.SECONDS)).thenReturn(expectedResult);
ScheduledFuture<?> result = executor.scheduleWithFixedDelay(runnable, 1, 2, TimeUnit.SECONDS);
assertThat(result).isEqualTo(expectedResult);
verify(delegate).scheduleWithFixedDelay(wrappedRunnable, 1, 2, TimeUnit.SECONDS);
}
@Override
protected abstract DelegatingSecurityContextScheduledExecutorService create();
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.mockito.Matchers.eq;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
import java.util.concurrent.Callable;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Abstract base class for testing classes that extend {@link AbstractDelegatingSecurityContextSupport}
*
* @author Rob Winch
* @since 3.2
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ DelegatingSecurityContextRunnable.class, DelegatingSecurityContextCallable.class })
public abstract class AbstractDelegatingSecurityContextTestSupport {
@Mock
protected SecurityContext securityContext;
@Mock
protected SecurityContext currentSecurityContext;
@Captor
protected ArgumentCaptor<SecurityContext> securityContextCaptor;
@Mock
protected Callable<Object> callable;
@Mock
protected Callable<Object> wrappedCallable;
@Mock
protected Runnable runnable;
@Mock
protected Runnable wrappedRunnable;
public final void explicitSecurityContextPowermockSetup() throws Exception {
spy(DelegatingSecurityContextCallable.class);
doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", eq(callable),
securityContextCaptor.capture());
spy(DelegatingSecurityContextRunnable.class);
doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", eq(runnable),
securityContextCaptor.capture());
}
public final void currentSecurityContextPowermockSetup() throws Exception {
spy(DelegatingSecurityContextCallable.class);
doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", callable, null);
spy(DelegatingSecurityContextRunnable.class);
doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", runnable, null);
}
@Before
public final void setContext() {
SecurityContextHolder.setContext(currentSecurityContext);
}
@After
public final void clearContext() {
SecurityContextHolder.clearContext();
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextExecutorService}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentDelegatingSecurityContextExecutorServiceTests extends AbstractDelegatingSecurityContextExecutorServiceTests{
@Before
public void setUp() throws Exception {
super.currentSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextExecutorService create() {
return new DelegatingSecurityContextExecutorService(delegate);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentDelegatingSecurityContextExecutorTests extends
AbstractDelegatingSecurityContextExecutorTests {
@Before
public void setUp() throws Exception {
super.currentSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextExecutor create() {
return new DelegatingSecurityContextExecutor(getExecutor());
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextScheduledExecutorService}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentDelegatingSecurityContextScheduledExecutorServiceTests extends
AbstractDelegatingSecurityContextScheduledExecutorServiceTests {
@Before
public void setUp() throws Exception {
this.currentSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextScheduledExecutorService create() {
return new DelegatingSecurityContextScheduledExecutorService(delegate);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.concurrent.Callable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.internal.stubbing.answers.Returns;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
*
* @author Rob Winch
* @since 3.2
*/
@RunWith(MockitoJUnitRunner.class)
public class DelegatingSecurityContextCallableTests {
@Mock
private Callable<Object> delegate;
@Mock
private SecurityContext securityContext;
@Mock
private Object callableResult;
private Callable<Object> callable;
@Before
@SuppressWarnings("serial")
public void setUp() throws Exception {
when(delegate.call()).thenAnswer(new Returns(callableResult) {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
assertThat(SecurityContextHolder.getContext()).isEqualTo(securityContext);
return super.answer(invocation);
}
});
}
@After
public void tearDown() {
SecurityContextHolder.clearContext();
}
// --- constructor ---
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegate() {
new DelegatingSecurityContextCallable<Object>(null);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegateNonNullSecurityContext() {
new DelegatingSecurityContextCallable<Object>(null, securityContext);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegateAndSecurityContext() {
new DelegatingSecurityContextCallable<Object>(null, null);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullSecurityContext() {
new DelegatingSecurityContextCallable<Object>(delegate, null);
}
// --- call ---
@Test
public void call() throws Exception {
callable = new DelegatingSecurityContextCallable<Object>(delegate, securityContext);
assertWrapped(callable.call());
}
@Test
public void callDefaultSecurityContext() throws Exception {
SecurityContextHolder.setContext(securityContext);
callable = new DelegatingSecurityContextCallable<Object>(delegate);
SecurityContextHolder.clearContext(); // ensure callable is what sets up the SecurityContextHolder
assertWrapped(callable.call());
}
// --- create ---
@Test(expected = IllegalArgumentException.class)
public void createNullDelegate() {
DelegatingSecurityContextCallable.create(null, securityContext);
}
@Test(expected = IllegalArgumentException.class)
public void createNullDelegateAndSecurityContext() {
DelegatingSecurityContextRunnable.create(null, null);
}
@Test
public void createNullSecurityContext() throws Exception {
SecurityContextHolder.setContext(securityContext);
callable = DelegatingSecurityContextCallable.create(delegate, null);
SecurityContextHolder.clearContext(); // ensure callable is what sets up the SecurityContextHolder
assertWrapped(callable.call());
}
@Test
public void create() throws Exception {
callable = DelegatingSecurityContextCallable.create(delegate, securityContext);
assertWrapped(callable.call());
}
private void assertWrapped(Object actualResult) throws Exception {
assertThat(actualResult).isEqualTo(callableResult);
verify(delegate).call();
assertThat(SecurityContextHolder.getContext()).isEqualTo(SecurityContextHolder.createEmptyContext());
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
*
* @author Rob Winch
* @since 3.2
*/
@RunWith(MockitoJUnitRunner.class)
public class DelegatingSecurityContextRunnableTests {
@Mock
private Runnable delegate;
@Mock
private SecurityContext securityContext;
@Mock
private Object callableResult;
private Runnable runnable;
@Before
public void setUp() throws Exception {
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
assertThat(SecurityContextHolder.getContext()).isEqualTo(securityContext);
return null;
}
})
.when(delegate).run();
}
@After
public void tearDown() {
SecurityContextHolder.clearContext();
}
// --- constructor ---
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegate() {
new DelegatingSecurityContextRunnable(null);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegateNonNullSecurityContext() {
new DelegatingSecurityContextRunnable(null, securityContext);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullDelegateAndSecurityContext() {
new DelegatingSecurityContextRunnable(null, null);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullSecurityContext() {
new DelegatingSecurityContextRunnable(delegate, null);
}
// --- run ---
@Test
public void call() throws Exception {
runnable = new DelegatingSecurityContextRunnable(delegate, securityContext);
runnable.run();
assertWrapped();
}
@Test
public void callDefaultSecurityContext() throws Exception {
SecurityContextHolder.setContext(securityContext);
runnable = new DelegatingSecurityContextRunnable(delegate);
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the SecurityContextHolder
runnable.run();
assertWrapped();
}
// --- create ---
@Test(expected = IllegalArgumentException.class)
public void createNullDelegate() {
DelegatingSecurityContextRunnable.create(null, securityContext);
}
@Test(expected = IllegalArgumentException.class)
public void createNullDelegateAndSecurityContext() {
DelegatingSecurityContextRunnable.create(null, null);
}
@Test
public void createNullSecurityContext() {
SecurityContextHolder.setContext(securityContext);
runnable = DelegatingSecurityContextRunnable.create(delegate, null);
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the SecurityContextHolder
runnable.run();
assertWrapped();
}
@Test
public void create() {
runnable = DelegatingSecurityContextRunnable.create(delegate, securityContext);
runnable.run();
assertWrapped();
}
private void assertWrapped() {
verify(delegate).run();
assertThat(SecurityContextHolder.getContext()).isEqualTo(SecurityContextHolder.createEmptyContext());
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2002-2012 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.concurrent;
import static org.fest.assertions.Assertions.assertThat;
import org.junit.Test;
import org.springframework.security.core.context.SecurityContext;
/**
*
* @author Rob Winch
* @since 3.2
*
*/
public class DelegatingSecurityContextSupportTests extends AbstractDelegatingSecurityContextTestSupport {
private AbstractDelegatingSecurityContextSupport support;
@Test
public void wrapCallable() throws Exception {
explicitSecurityContextPowermockSetup();
support = new ConcreteDelegatingSecurityContextSupport(securityContext);
assertThat(support.wrap(callable)).isSameAs(wrappedCallable);
assertThat(securityContextCaptor.getValue()).isSameAs(securityContext);
}
@Test
public void wrapCallableNullSecurityContext() throws Exception {
currentSecurityContextPowermockSetup();
support = new ConcreteDelegatingSecurityContextSupport(null);
assertThat(support.wrap(callable)).isSameAs(wrappedCallable);
}
@Test
public void wrapRunnable() throws Exception {
explicitSecurityContextPowermockSetup();
support = new ConcreteDelegatingSecurityContextSupport(securityContext);
assertThat(support.wrap(runnable)).isSameAs(wrappedRunnable);
assertThat(securityContextCaptor.getValue()).isSameAs(securityContext);
}
@Test
public void wrapRunnableNullSecurityContext() throws Exception {
currentSecurityContextPowermockSetup();
support = new ConcreteDelegatingSecurityContextSupport(null);
assertThat(support.wrap(runnable)).isSameAs(wrappedRunnable);
}
private static class ConcreteDelegatingSecurityContextSupport extends AbstractDelegatingSecurityContextSupport {
public ConcreteDelegatingSecurityContextSupport(SecurityContext securityContext) {
super(securityContext);
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
/**
* Tests Explicitly specifying the {@link SecurityContext} on {@link DelegatingSecurityContextExecutorService}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitDelegatingSecurityContextExecutorServiceTests extends AbstractDelegatingSecurityContextExecutorServiceTests{
@Before
public void setUp() throws Exception {
super.explicitSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextExecutorService create() {
return new DelegatingSecurityContextExecutorService(delegate,securityContext);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
import org.springframework.security.core.context.SecurityContext;
/**
* Tests Explicitly specifying the {@link SecurityContext} on {@link DelegatingSecurityContextExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitDelegatingSecurityContextExecutorTests extends
AbstractDelegatingSecurityContextExecutorTests {
@Before
public void setUp() throws Exception {
super.explicitSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextExecutor create() {
return new DelegatingSecurityContextExecutor(getExecutor(), securityContext);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 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.concurrent;
import org.junit.Before;
import org.springframework.security.core.context.SecurityContext;
/**
* Tests Explicitly specifying the {@link SecurityContext} on {@link DelegatingSecurityContextScheduledExecutorService}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitDelegatingSecurityContextScheduledExecutorServiceTests extends
AbstractDelegatingSecurityContextScheduledExecutorServiceTests {
@Before
public void setUp() throws Exception {
this.explicitSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextScheduledExecutorService create() {
return new DelegatingSecurityContextScheduledExecutorService(delegate, securityContext);
}
}

View File

@@ -0,0 +1,39 @@
package org.springframework.security.scheduling;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.mockito.Mock;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.security.task.AbstractDelegatingSecurityContextAsyncTaskExecutorTests;
/**
* Abstract class for testing {@link DelegatingSecurityContextSchedulingTaskExecutor} which allows customization of
* how {@link DelegatingSecurityContextSchedulingTaskExecutor} and its mocks are created.
*
* @author Rob Winch
* @since 3.2
* @see CurrentSecurityContextSchedulingTaskExecutorTests
* @see ExplicitSecurityContextSchedulingTaskExecutorTests
*/
public abstract class AbstractSecurityContextSchedulingTaskExecutorTests extends
AbstractDelegatingSecurityContextAsyncTaskExecutorTests {
@Mock
protected SchedulingTaskExecutor taskExecutorDelegate;
private DelegatingSecurityContextSchedulingTaskExecutor executor;
@Test
public void prefersShortLivedTasks() {
executor = create();
executor.prefersShortLivedTasks();
verify(taskExecutorDelegate).prefersShortLivedTasks();
}
protected SchedulingTaskExecutor getExecutor() {
return taskExecutorDelegate;
}
protected abstract DelegatingSecurityContextSchedulingTaskExecutor create();
}

View File

@@ -0,0 +1,23 @@
package org.springframework.security.scheduling;
import org.junit.Before;
import org.springframework.security.core.context.SecurityContext;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextSchedulingTaskExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentSecurityContextSchedulingTaskExecutorTests extends AbstractSecurityContextSchedulingTaskExecutorTests {
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
}
protected DelegatingSecurityContextSchedulingTaskExecutor create() {
return new DelegatingSecurityContextSchedulingTaskExecutor(taskExecutorDelegate);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 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.scheduling;
import org.junit.Before;
import org.springframework.security.core.context.SecurityContext;
/**
* Tests Explicitly specifying the {@link SecurityContext} on {@link DelegatingSecurityContextSchedulingTaskExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitSecurityContextSchedulingTaskExecutorTests extends AbstractSecurityContextSchedulingTaskExecutorTests {
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
}
protected DelegatingSecurityContextSchedulingTaskExecutor create() {
return new DelegatingSecurityContextSchedulingTaskExecutor(taskExecutorDelegate, securityContext);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2002-2012 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.task;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.security.concurrent.AbstractDelegatingSecurityContextExecutorTests;
/**
* Abstract class for testing {@link DelegatingSecurityContextAsyncTaskExecutor} which allows customization of
* how {@link DelegatingSecurityContextAsyncTaskExecutor} and its mocks are created.
*
* @author Rob Winch
* @since 3.2
* @see CurrentDelegatingSecurityContextAsyncTaskExecutorTests
* @see ExplicitDelegatingSecurityContextAsyncTaskExecutorTests
*/
public abstract class AbstractDelegatingSecurityContextAsyncTaskExecutorTests extends AbstractDelegatingSecurityContextExecutorTests {
@Mock
protected AsyncTaskExecutor taskExecutorDelegate;
private DelegatingSecurityContextAsyncTaskExecutor executor;
@Before
public final void setUpExecutor() {
executor = create();
}
@Test
public void executeStartTimeout() {
executor.execute(runnable, 1);
verify(getExecutor()).execute(wrappedRunnable, 1);
}
@Test
public void submit() {
executor.submit(runnable);
verify(getExecutor()).submit(wrappedRunnable);
}
@Test
public void submitCallable() {
executor.submit(callable);
verify(getExecutor()).submit(wrappedCallable);
}
protected AsyncTaskExecutor getExecutor() {
return taskExecutorDelegate;
}
protected abstract DelegatingSecurityContextAsyncTaskExecutor create();
}

View File

@@ -0,0 +1,26 @@
package org.springframework.security.task;
import org.junit.Before;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextAsyncTaskExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentDelegatingSecurityContextAsyncTaskExecutorTests extends
AbstractDelegatingSecurityContextAsyncTaskExecutorTests {
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextAsyncTaskExecutor create() {
return new DelegatingSecurityContextAsyncTaskExecutor(taskExecutorDelegate);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 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.task;
import java.util.concurrent.Executor;
import org.junit.Before;
import org.mockito.Mock;
import org.springframework.core.task.TaskExecutor;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import org.springframework.security.concurrent.AbstractDelegatingSecurityContextExecutorTests;
/**
* Tests using the current {@link SecurityContext} on {@link DelegatingSecurityContextExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class CurrentDelegatingSecurityContextTaskExecutorTests extends AbstractDelegatingSecurityContextExecutorTests {
@Mock
private TaskExecutor taskExecutorDelegate;
@Before
public void setUp() throws Exception {
currentSecurityContextPowermockSetup();
}
protected Executor getExecutor() {
return taskExecutorDelegate;
}
protected DelegatingSecurityContextExecutor create() {
return new DelegatingSecurityContextTaskExecutor(taskExecutorDelegate);
}
}

View File

@@ -0,0 +1,26 @@
package org.springframework.security.task;
import org.junit.Before;
/**
* Tests using an explicit {@link SecurityContext} on {@link DelegatingSecurityContextAsyncTaskExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitDelegatingSecurityContextAsyncTaskExecutorTests extends
AbstractDelegatingSecurityContextAsyncTaskExecutorTests {
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
}
@Override
protected DelegatingSecurityContextAsyncTaskExecutor create() {
return new DelegatingSecurityContextAsyncTaskExecutor(taskExecutorDelegate, securityContext);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2002-2012 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.task;
import java.util.concurrent.Executor;
import org.junit.Before;
import org.mockito.Mock;
import org.springframework.core.task.TaskExecutor;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import org.springframework.security.concurrent.AbstractDelegatingSecurityContextExecutorTests;
/**
* Tests using the an explicit {@link SecurityContext} on {@link DelegatingSecurityContextExecutor}
*
* @author Rob Winch
* @since 3.2
*
*/
public class ExplicitDelegatingSecurityContextTaskExecutorTests extends AbstractDelegatingSecurityContextExecutorTests {
@Mock
private TaskExecutor taskExecutorDelegate;
@Before
public void setUp() throws Exception {
explicitSecurityContextPowermockSetup();
}
protected Executor getExecutor() {
return taskExecutorDelegate;
}
protected DelegatingSecurityContextExecutor create() {
return new DelegatingSecurityContextTaskExecutor(taskExecutorDelegate, securityContext);
}
}