diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssert.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssert.java new file mode 100644 index 0000000000..3e7fbde2ab --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssert.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-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.boot.testsupport.assertj; + +import java.lang.reflect.Field; + +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Assert; + +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.util.ReflectionUtils; + +/** + * AssertJ {@link Assert} for {@link SimpleAsyncTaskExecutor}. + * + * @author Moritz Halbritter + * @since 3.2.0 + */ +public final class SimpleAsyncTaskExecutorAssert + extends AbstractAssert { + + private SimpleAsyncTaskExecutorAssert(SimpleAsyncTaskExecutor actual) { + super(actual, SimpleAsyncTaskExecutorAssert.class); + } + + /** + * Verifies that the actual executor uses platform threads. + * @return {@code this} assertion object + * @throws AssertionError if the actual executor doesn't use platform threads + */ + public SimpleAsyncTaskExecutorAssert usesPlatformThreads() { + isNotNull(); + if (producesVirtualThreads()) { + failWithMessage("Expected executor to use platform threads, but it uses virtual threads"); + } + return this; + } + + /** + * Verifies that the actual executor uses virtual threads. + * @return {@code this} assertion object + * @throws AssertionError if the actual executor doesn't use virtual threads + */ + public SimpleAsyncTaskExecutorAssert usesVirtualThreads() { + isNotNull(); + if (!producesVirtualThreads()) { + failWithMessage("Expected executor to use virtual threads, but it uses platform threads"); + } + return this; + } + + private boolean producesVirtualThreads() { + Field field = ReflectionUtils.findField(SimpleAsyncTaskExecutor.class, "virtualThreadDelegate"); + if (field == null) { + throw new IllegalStateException("Field SimpleAsyncTaskExecutor.virtualThreadDelegate not found"); + } + ReflectionUtils.makeAccessible(field); + Object virtualThreadDelegate = ReflectionUtils.getField(field, this.actual); + return virtualThreadDelegate != null; + } + + /** + * Creates a new assertion class with the given {@link SimpleAsyncTaskExecutor}. + * @param actual the {@link SimpleAsyncTaskExecutor} + * @return the assertion class + */ + public static SimpleAsyncTaskExecutorAssert assertThat(SimpleAsyncTaskExecutor actual) { + return new SimpleAsyncTaskExecutorAssert(actual); + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/package-info.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/package-info.java new file mode 100644 index 0000000000..51fb5eaf4e --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/assertj/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2021 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. + */ + +/** + * Custom AssertJ assertions. + */ +package org.springframework.boot.testsupport.assertj; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/test/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssertTests.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/test/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssertTests.java new file mode 100644 index 0000000000..a3775298f8 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/test/java/org/springframework/boot/testsupport/assertj/SimpleAsyncTaskExecutorAssertTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-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.boot.testsupport.assertj; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; + +import org.springframework.core.task.SimpleAsyncTaskExecutor; + +/** + * Tests for {@link SimpleAsyncTaskExecutorAssert}. + * + * @author Moritz Halbritter + */ +class SimpleAsyncTaskExecutorAssertTests { + + @Test + void usesPlatformThreads() { + SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(); + executor.setVirtualThreads(false); + SimpleAsyncTaskExecutorAssert.assertThat(executor).usesPlatformThreads(); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void usesVirtualThreads() { + SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(); + executor.setVirtualThreads(true); + SimpleAsyncTaskExecutorAssert.assertThat(executor).usesVirtualThreads(); + } + +}