Add integration tests for virtual threads
Closes gh-12790
This commit is contained in:
parent
ecf8467cac
commit
247ce5dcab
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2002-2023 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public final class DelegatingSecurityContextTestUtils {
|
||||
|
||||
private DelegatingSecurityContextTestUtils() {
|
||||
}
|
||||
|
||||
public static <T extends Executor> SecurityContext runAndReturn(ThreadFactory threadFactory,
|
||||
Function<ScheduledExecutorService, T> factory, BiConsumer<T, Runnable> fn) throws Exception {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
AtomicReference<SecurityContext> result = new AtomicReference<>();
|
||||
ScheduledExecutorService delegate = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||
try {
|
||||
T executor = factory.apply(delegate);
|
||||
Runnable task = () -> {
|
||||
result.set(SecurityContextHolder.getContext());
|
||||
countDownLatch.countDown();
|
||||
};
|
||||
fn.accept(executor, task);
|
||||
countDownLatch.await();
|
||||
|
||||
return result.get();
|
||||
}
|
||||
finally {
|
||||
delegate.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends TaskScheduler> SecurityContext runAndReturn(ThreadFactory threadFactory,
|
||||
Function<ScheduledExecutorService, T> factory, BiFunction<T, Runnable, ScheduledFuture<?>> fn)
|
||||
throws Exception {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
AtomicReference<SecurityContext> result = new AtomicReference<>();
|
||||
ScheduledExecutorService delegate = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||
try {
|
||||
T taskScheduler = factory.apply(delegate);
|
||||
Runnable task = () -> {
|
||||
result.set(SecurityContextHolder.getContext());
|
||||
countDownLatch.countDown();
|
||||
};
|
||||
ScheduledFuture<?> future = fn.apply(taskScheduler, task);
|
||||
countDownLatch.await();
|
||||
future.cancel(false);
|
||||
|
||||
return result.get();
|
||||
}
|
||||
finally {
|
||||
delegate.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Executor> SecurityContext callAndReturn(ThreadFactory threadFactory,
|
||||
Function<ScheduledExecutorService, T> factory,
|
||||
BiFunction<T, Callable<SecurityContext>, Future<SecurityContext>> fn) throws Exception {
|
||||
ScheduledExecutorService delegate = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||
try {
|
||||
T executor = factory.apply(delegate);
|
||||
Callable<SecurityContext> task = SecurityContextHolder::getContext;
|
||||
return fn.apply(executor, task).get();
|
||||
}
|
||||
finally {
|
||||
delegate.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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 java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextExecutorIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
Executor::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextExecutor createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextExecutor(delegate, securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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 java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextExecutorServiceIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
ExecutorService::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
ExecutorService::submit
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextExecutorService createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextExecutorService(delegate, securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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 java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextScheduledExecutorServiceIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
ScheduledExecutorService::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
ScheduledExecutorService::submit
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void scheduleWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext scheduleAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
(executor, task) -> executor.schedule(task, 50, TimeUnit.MILLISECONDS)
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextScheduledExecutorService createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextScheduledExecutorService(delegate, securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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 java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.scheduling.SchedulingTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextSchedulingTaskExecutorIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
SchedulingTaskExecutor::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeCompletableWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeCompletableAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeCompletableWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeCompletableAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeCompletableAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
SchedulingTaskExecutor::submitCompletable
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
SchedulingTaskExecutor::submit
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitCompletableWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitCompletableAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitCompletableWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitCompletableAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitCompletableAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(
|
||||
threadFactory,
|
||||
this::createExecutor,
|
||||
SchedulingTaskExecutor::submitCompletable
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextSchedulingTaskExecutor createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextSchedulingTaskExecutor(new ConcurrentTaskExecutor(delegate),
|
||||
securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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 java.time.Duration;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextTaskSchedulerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void scheduleWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void scheduleWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext scheduleAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createTaskScheduler,
|
||||
(taskScheduler, task) -> taskScheduler.schedule(task, new PeriodicTrigger(Duration.ofMillis(50)))
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleAtFixedRateWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAtFixedRateAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void scheduleAtFixedRateWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleAtFixedRateAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext scheduleAtFixedRateAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createTaskScheduler,
|
||||
(taskScheduler, task) -> taskScheduler.scheduleAtFixedRate(task, Duration.ofMillis(50))
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleWithFixedDelayWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleWithFixedDelayAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void scheduleWithFixedDelayWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = scheduleWithFixedDelayAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext scheduleWithFixedDelayAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(
|
||||
threadFactory,
|
||||
this::createTaskScheduler,
|
||||
(taskScheduler, task) -> taskScheduler.scheduleWithFixedDelay(task, Duration.ofMillis(50))
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextTaskScheduler createTaskScheduler(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextTaskScheduler(new ConcurrentTaskScheduler(delegate), securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextAsyncTaskExecutorIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(threadFactory,
|
||||
this::createExecutor,
|
||||
AsyncTaskExecutor::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeCompletableWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeCompletableAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeCompletableWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeCompletableAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeCompletableAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(threadFactory,
|
||||
this::createExecutor,
|
||||
AsyncTaskExecutor::submitCompletable
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(threadFactory,
|
||||
this::createExecutor,
|
||||
AsyncTaskExecutor::submit
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitCompletableWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitCompletableAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void submitCompletableWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = submitCompletableAndReturn(
|
||||
new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext submitCompletableAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.callAndReturn(threadFactory,
|
||||
this::createExecutor,
|
||||
AsyncTaskExecutor::submitCompletable
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextAsyncTaskExecutor createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextAsyncTaskExecutor(new TaskExecutorAdapter(delegate), securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2020-2023 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
|
||||
*
|
||||
* https://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.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
import org.springframework.security.DelegatingSecurityContextTestUtils;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class DelegatingSecurityContextTaskExecutorIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void executeWhenThreadFactoryIsPlatformThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(Executors.defaultThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_17)
|
||||
public void executeWhenThreadFactoryIsVirtualThenSecurityContextPropagated() throws Exception {
|
||||
SecurityContext securityContext = executeAndReturn(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
|
||||
assertThat(securityContext.getAuthentication()).isNotNull();
|
||||
}
|
||||
|
||||
private SecurityContext executeAndReturn(ThreadFactory threadFactory) throws Exception {
|
||||
// @formatter:off
|
||||
return DelegatingSecurityContextTestUtils.runAndReturn(threadFactory,
|
||||
this::createExecutor,
|
||||
TaskExecutor::execute
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private DelegatingSecurityContextTaskExecutor createExecutor(ScheduledExecutorService delegate) {
|
||||
return new DelegatingSecurityContextTaskExecutor(new TaskExecutorAdapter(delegate), securityContext());
|
||||
}
|
||||
|
||||
private static SecurityContext securityContext() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new TestingAuthenticationToken("user", null));
|
||||
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue