Make TaskExecutor and TaskScheduler tests more robust
This commit is contained in:
parent
c4ef002392
commit
763f7b9be8
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -23,11 +23,13 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
|
@ -41,24 +43,27 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|||
* @author Sam Brannen
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public abstract class AbstractSchedulingTaskExecutorTests {
|
||||
abstract class AbstractSchedulingTaskExecutorTests {
|
||||
|
||||
static final String THREAD_NAME_PREFIX = "test-";
|
||||
|
||||
private AsyncListenableTaskExecutor executor;
|
||||
|
||||
protected String testName;
|
||||
|
||||
private volatile Object outcome;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void initExecutor() {
|
||||
executor = buildExecutor();
|
||||
void setUp(TestInfo testInfo) {
|
||||
this.testName = testInfo.getTestMethod().get().getName();
|
||||
this.executor = buildExecutor();
|
||||
}
|
||||
|
||||
protected abstract AsyncListenableTaskExecutor buildExecutor();
|
||||
|
||||
@AfterEach
|
||||
public void shutdownExecutor() throws Exception {
|
||||
void shutdownExecutor() throws Exception {
|
||||
if (executor instanceof DisposableBean) {
|
||||
((DisposableBean) executor).destroy();
|
||||
}
|
||||
|
@ -66,23 +71,28 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
|
||||
|
||||
@Test
|
||||
public void executeRunnable() {
|
||||
TestTask task = new TestTask(1);
|
||||
void executeRunnable() {
|
||||
TestTask task = new TestTask(this.testName, 1);
|
||||
executor.execute(task);
|
||||
await(task);
|
||||
assertThreadNamePrefix(task);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeFailingRunnable() {
|
||||
TestTask task = new TestTask(0);
|
||||
void executeFailingRunnable() {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
executor.execute(task);
|
||||
// nothing to assert
|
||||
Awaitility.await()
|
||||
.dontCatchUncaughtExceptions()
|
||||
.atMost(1, TimeUnit.SECONDS)
|
||||
.pollInterval(10, TimeUnit.MILLISECONDS)
|
||||
.until(() -> task.exception.get() != null && task.exception.get().getMessage().equals(
|
||||
"TestTask failure for test 'executeFailingRunnable': expectedRunCount:<0>, actualRunCount:<1>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitRunnable() throws Exception {
|
||||
TestTask task = new TestTask(1);
|
||||
void submitRunnable() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 1);
|
||||
Future<?> future = executor.submit(task);
|
||||
Object result = future.get(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNull();
|
||||
|
@ -90,8 +100,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingRunnable() throws Exception {
|
||||
TestTask task = new TestTask(0);
|
||||
void submitFailingRunnable() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
Future<?> future = executor.submit(task);
|
||||
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
|
||||
future.get(1000, TimeUnit.MILLISECONDS));
|
||||
|
@ -99,9 +109,9 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitRunnableWithGetAfterShutdown() throws Exception {
|
||||
Future<?> future1 = executor.submit(new TestTask(-1));
|
||||
Future<?> future2 = executor.submit(new TestTask(-1));
|
||||
void submitRunnableWithGetAfterShutdown() throws Exception {
|
||||
Future<?> future1 = executor.submit(new TestTask(this.testName, -1));
|
||||
Future<?> future2 = executor.submit(new TestTask(this.testName, -1));
|
||||
shutdownExecutor();
|
||||
assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> {
|
||||
future1.get(1000, TimeUnit.MILLISECONDS);
|
||||
|
@ -110,8 +120,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitListenableRunnable() throws Exception {
|
||||
TestTask task = new TestTask(1);
|
||||
void submitListenableRunnable() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 1);
|
||||
// Act
|
||||
ListenableFuture<?> future = executor.submitListenable(task);
|
||||
future.addCallback(result -> outcome = result, ex -> outcome = ex);
|
||||
|
@ -125,8 +135,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingListenableRunnable() throws Exception {
|
||||
TestTask task = new TestTask(0);
|
||||
void submitFailingListenableRunnable() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
ListenableFuture<?> future = executor.submitListenable(task);
|
||||
future.addCallback(result -> outcome = result, ex -> outcome = ex);
|
||||
|
||||
|
@ -139,9 +149,9 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitListenableRunnableWithGetAfterShutdown() throws Exception {
|
||||
ListenableFuture<?> future1 = executor.submitListenable(new TestTask(-1));
|
||||
ListenableFuture<?> future2 = executor.submitListenable(new TestTask(-1));
|
||||
void submitListenableRunnableWithGetAfterShutdown() throws Exception {
|
||||
ListenableFuture<?> future1 = executor.submitListenable(new TestTask(this.testName, -1));
|
||||
ListenableFuture<?> future2 = executor.submitListenable(new TestTask(this.testName, -1));
|
||||
shutdownExecutor();
|
||||
|
||||
try {
|
||||
|
@ -159,16 +169,16 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(1);
|
||||
void submitCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(this.testName, 1);
|
||||
Future<String> future = executor.submit(task);
|
||||
String result = future.get(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result.substring(0, THREAD_NAME_PREFIX.length())).isEqualTo(THREAD_NAME_PREFIX);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(0);
|
||||
void submitFailingCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(this.testName, 0);
|
||||
Future<String> future = executor.submit(task);
|
||||
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
|
||||
future.get(1000, TimeUnit.MILLISECONDS));
|
||||
|
@ -176,9 +186,9 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitCallableWithGetAfterShutdown() throws Exception {
|
||||
Future<?> future1 = executor.submit(new TestCallable(-1));
|
||||
Future<?> future2 = executor.submit(new TestCallable(-1));
|
||||
void submitCallableWithGetAfterShutdown() throws Exception {
|
||||
Future<?> future1 = executor.submit(new TestCallable(this.testName, -1));
|
||||
Future<?> future2 = executor.submit(new TestCallable(this.testName, -1));
|
||||
shutdownExecutor();
|
||||
|
||||
try {
|
||||
|
@ -196,8 +206,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitListenableCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(1);
|
||||
void submitListenableCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(this.testName, 1);
|
||||
// Act
|
||||
ListenableFuture<String> future = executor.submitListenable(task);
|
||||
future.addCallback(result -> outcome = result, ex -> outcome = ex);
|
||||
|
@ -210,8 +220,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingListenableCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(0);
|
||||
void submitFailingListenableCallable() throws Exception {
|
||||
TestCallable task = new TestCallable(this.testName, 0);
|
||||
// Act
|
||||
ListenableFuture<String> future = executor.submitListenable(task);
|
||||
future.addCallback(result -> outcome = result, ex -> outcome = ex);
|
||||
|
@ -225,9 +235,9 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitListenableCallableWithGetAfterShutdown() throws Exception {
|
||||
ListenableFuture<?> future1 = executor.submitListenable(new TestCallable(-1));
|
||||
ListenableFuture<?> future2 = executor.submitListenable(new TestCallable(-1));
|
||||
void submitListenableCallableWithGetAfterShutdown() throws Exception {
|
||||
ListenableFuture<?> future1 = executor.submitListenable(new TestCallable(this.testName, -1));
|
||||
ListenableFuture<?> future2 = executor.submitListenable(new TestCallable(this.testName, -1));
|
||||
shutdownExecutor();
|
||||
assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> {
|
||||
future1.get(1000, TimeUnit.MILLISECONDS);
|
||||
|
@ -255,17 +265,22 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
|
||||
private static class TestTask implements Runnable {
|
||||
static class TestTask implements Runnable {
|
||||
|
||||
private final int expectedRunCount;
|
||||
|
||||
private final String testName;
|
||||
|
||||
private final AtomicInteger actualRunCount = new AtomicInteger();
|
||||
|
||||
private final CountDownLatch latch;
|
||||
private final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
|
||||
private Thread lastThread;
|
||||
final CountDownLatch latch;
|
||||
|
||||
TestTask(int expectedRunCount) {
|
||||
Thread lastThread;
|
||||
|
||||
TestTask(String testName, int expectedRunCount) {
|
||||
this.testName = testName;
|
||||
this.expectedRunCount = expectedRunCount;
|
||||
this.latch = (expectedRunCount > 0 ? new CountDownLatch(expectedRunCount) : null);
|
||||
}
|
||||
|
@ -280,7 +295,10 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
if (expectedRunCount >= 0) {
|
||||
if (actualRunCount.incrementAndGet() > expectedRunCount) {
|
||||
throw new RuntimeException("intentional test failure");
|
||||
RuntimeException exception = new RuntimeException(String.format("%s failure for test '%s': expectedRunCount:<%d>, actualRunCount:<%d>",
|
||||
getClass().getSimpleName(), this.testName, expectedRunCount, actualRunCount.get()));
|
||||
this.exception.set(exception);
|
||||
throw exception;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
|
@ -288,13 +306,16 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
|
||||
|
||||
private static class TestCallable implements Callable<String> {
|
||||
static class TestCallable implements Callable<String> {
|
||||
|
||||
private final String testName;
|
||||
|
||||
private final int expectedRunCount;
|
||||
|
||||
private final AtomicInteger actualRunCount = new AtomicInteger();
|
||||
|
||||
TestCallable(int expectedRunCount) {
|
||||
TestCallable(String testName, int expectedRunCount) {
|
||||
this.testName = testName;
|
||||
this.expectedRunCount = expectedRunCount;
|
||||
}
|
||||
|
||||
|
@ -307,7 +328,8 @@ public abstract class AbstractSchedulingTaskExecutorTests {
|
|||
}
|
||||
if (expectedRunCount >= 0) {
|
||||
if (actualRunCount.incrementAndGet() > expectedRunCount) {
|
||||
throw new RuntimeException("intentional test failure");
|
||||
throw new RuntimeException(String.format("%s failure for test '%s': expectedRunCount:<%d>, actualRunCount:<%d>",
|
||||
getClass().getSimpleName(), this.testName, expectedRunCount, actualRunCount.get()));
|
||||
}
|
||||
}
|
||||
return Thread.currentThread().getName();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.scheduling.concurrent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
@ -28,11 +27,13 @@ import org.junit.jupiter.api.Test;
|
|||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.NoOpRunnable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
|
||||
private final ThreadPoolExecutor concurrentExecutor =
|
||||
new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
|
||||
|
@ -46,9 +47,8 @@ public class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorT
|
|||
|
||||
@Override
|
||||
@AfterEach
|
||||
public void shutdownExecutor() {
|
||||
List<Runnable> remainingTasks = concurrentExecutor.shutdownNow();
|
||||
for (Runnable task : remainingTasks) {
|
||||
void shutdownExecutor() {
|
||||
for (Runnable task : concurrentExecutor.shutdownNow()) {
|
||||
if (task instanceof RunnableFuture) {
|
||||
((RunnableFuture<?>) task).cancel(true);
|
||||
}
|
||||
|
@ -57,25 +57,22 @@ public class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorT
|
|||
|
||||
|
||||
@Test
|
||||
public void zeroArgCtorResultsInDefaultTaskExecutorBeingUsed() {
|
||||
void zeroArgCtorResultsInDefaultTaskExecutorBeingUsed() {
|
||||
ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
|
||||
// must not throw a NullPointerException
|
||||
executor.execute(new NoOpRunnable());
|
||||
assertThatCode(() -> executor.execute(new NoOpRunnable())).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passingNullExecutorToCtorResultsInDefaultTaskExecutorBeingUsed() {
|
||||
void passingNullExecutorToCtorResultsInDefaultTaskExecutorBeingUsed() {
|
||||
ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor(null);
|
||||
// must not throw a NullPointerException
|
||||
executor.execute(new NoOpRunnable());
|
||||
assertThatCode(() -> executor.execute(new NoOpRunnable())).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passingNullExecutorToSetterResultsInDefaultTaskExecutorBeingUsed() {
|
||||
void passingNullExecutorToSetterResultsInDefaultTaskExecutorBeingUsed() {
|
||||
ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
|
||||
executor.setConcurrentExecutor(null);
|
||||
// must not throw a NullPointerException
|
||||
executor.execute(new NoOpRunnable());
|
||||
assertThatCode(() -> executor.execute(new NoOpRunnable())).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -24,7 +24,7 @@ import org.springframework.scheduling.support.TaskUtils;
|
|||
* @author Juergen Hoeller
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
|
||||
@Override
|
||||
protected AsyncListenableTaskExecutor buildExecutor() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -38,17 +38,17 @@ import static org.springframework.core.testfixture.TestGroup.PERFORMANCE;
|
|||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ScheduledExecutorFactoryBeanTests {
|
||||
class ScheduledExecutorFactoryBeanTests {
|
||||
|
||||
@Test
|
||||
public void testThrowsExceptionIfPoolSizeIsLessThanZero() throws Exception {
|
||||
void throwsExceptionIfPoolSizeIsLessThanZero() throws Exception {
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> factory.setPoolSize(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void testShutdownNowIsPropagatedToTheExecutorOnDestroy() throws Exception {
|
||||
void shutdownNowIsPropagatedToTheExecutorOnDestroy() throws Exception {
|
||||
final ScheduledExecutorService executor = mock(ScheduledExecutorService.class);
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
|
||||
|
@ -57,9 +57,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
return executor;
|
||||
}
|
||||
};
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
|
||||
new NoOpScheduledExecutorTask()
|
||||
});
|
||||
factory.setScheduledExecutorTasks(new NoOpScheduledExecutorTask());
|
||||
factory.afterPropertiesSet();
|
||||
factory.destroy();
|
||||
|
||||
|
@ -68,7 +66,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void testShutdownIsPropagatedToTheExecutorOnDestroy() throws Exception {
|
||||
void shutdownIsPropagatedToTheExecutorOnDestroy() throws Exception {
|
||||
final ScheduledExecutorService executor = mock(ScheduledExecutorService.class);
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
|
||||
|
@ -77,9 +75,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
return executor;
|
||||
}
|
||||
};
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
|
||||
new NoOpScheduledExecutorTask()
|
||||
});
|
||||
factory.setScheduledExecutorTasks(new NoOpScheduledExecutorTask());
|
||||
factory.setWaitForTasksToCompleteOnShutdown(true);
|
||||
factory.afterPropertiesSet();
|
||||
factory.destroy();
|
||||
|
@ -89,13 +85,11 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@EnabledForTestGroups(PERFORMANCE)
|
||||
public void testOneTimeExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
void oneTimeExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
|
||||
new ScheduledExecutorTask(runnable)
|
||||
});
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask(runnable));
|
||||
factory.afterPropertiesSet();
|
||||
pauseToLetTaskStart(1);
|
||||
factory.destroy();
|
||||
|
@ -105,7 +99,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@EnabledForTestGroups(PERFORMANCE)
|
||||
public void testFixedRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
void fixedRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
|
||||
ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
|
||||
|
@ -113,7 +107,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
task.setFixedRate(true);
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{task});
|
||||
factory.setScheduledExecutorTasks(task);
|
||||
factory.afterPropertiesSet();
|
||||
pauseToLetTaskStart(2);
|
||||
factory.destroy();
|
||||
|
@ -123,7 +117,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@EnabledForTestGroups(PERFORMANCE)
|
||||
public void testFixedRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
|
||||
void fixedRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
willThrow(new IllegalStateException()).given(runnable).run();
|
||||
|
||||
|
@ -132,7 +126,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
task.setFixedRate(true);
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{task});
|
||||
factory.setScheduledExecutorTasks(task);
|
||||
factory.setContinueScheduledExecutionAfterException(true);
|
||||
factory.afterPropertiesSet();
|
||||
pauseToLetTaskStart(2);
|
||||
|
@ -143,7 +137,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@EnabledForTestGroups(PERFORMANCE)
|
||||
public void testWithInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
void withInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
|
||||
ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
|
||||
|
@ -151,7 +145,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
task.setDelay(3000); // nice long wait...
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[] {task});
|
||||
factory.setScheduledExecutorTasks(task);
|
||||
factory.afterPropertiesSet();
|
||||
pauseToLetTaskStart(1);
|
||||
// invoke destroy before tasks have even been scheduled...
|
||||
|
@ -163,7 +157,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@EnabledForTestGroups(PERFORMANCE)
|
||||
public void testWithInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
|
||||
void withInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
willThrow(new IllegalStateException()).given(runnable).run();
|
||||
|
||||
|
@ -172,7 +166,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
task.setDelay(3000); // nice long wait...
|
||||
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[] {task});
|
||||
factory.setScheduledExecutorTasks(task);
|
||||
factory.setContinueScheduledExecutionAfterException(true);
|
||||
factory.afterPropertiesSet();
|
||||
pauseToLetTaskStart(1);
|
||||
|
@ -185,7 +179,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void testSettingThreadFactoryToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
|
||||
void settingThreadFactoryToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
|
||||
@Override
|
||||
protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||
|
@ -193,9 +187,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
return super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler);
|
||||
}
|
||||
};
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
|
||||
new NoOpScheduledExecutorTask()
|
||||
});
|
||||
factory.setScheduledExecutorTasks(new NoOpScheduledExecutorTask());
|
||||
factory.setThreadFactory(null); // the null must not propagate
|
||||
factory.afterPropertiesSet();
|
||||
factory.destroy();
|
||||
|
@ -203,7 +195,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void testSettingRejectedExecutionHandlerToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
|
||||
void settingRejectedExecutionHandlerToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
|
||||
@Override
|
||||
protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||
|
@ -211,16 +203,14 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
return super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler);
|
||||
}
|
||||
};
|
||||
factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
|
||||
new NoOpScheduledExecutorTask()
|
||||
});
|
||||
factory.setScheduledExecutorTasks(new NoOpScheduledExecutorTask());
|
||||
factory.setRejectedExecutionHandler(null); // the null must not propagate
|
||||
factory.afterPropertiesSet();
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectTypeReportsCorrectType() throws Exception {
|
||||
void objectTypeReportsCorrectType() throws Exception {
|
||||
ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
|
||||
assertThat(factory.getObjectType()).isEqualTo(ScheduledExecutorService.class);
|
||||
}
|
||||
|
@ -237,7 +227,7 @@ public class ScheduledExecutorFactoryBeanTests {
|
|||
|
||||
private static class NoOpScheduledExecutorTask extends ScheduledExecutorTask {
|
||||
|
||||
public NoOpScheduledExecutorTask() {
|
||||
NoOpScheduledExecutorTask() {
|
||||
super(new NoOpRunnable());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ThreadPoolExecutorFactoryBeanTests {
|
||||
class ThreadPoolExecutorFactoryBeanTests {
|
||||
|
||||
@Test
|
||||
public void defaultExecutor() throws Exception {
|
||||
void defaultExecutor() throws Exception {
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ExecutorConfig.class);
|
||||
ExecutorService executor = context.getBean(ExecutorService.class);
|
||||
|
||||
|
@ -46,10 +46,10 @@ public class ThreadPoolExecutorFactoryBeanTests {
|
|||
|
||||
|
||||
@Configuration
|
||||
public static class ExecutorConfig {
|
||||
static class ExecutorConfig {
|
||||
|
||||
@Bean
|
||||
public ThreadPoolExecutorFactoryBean executor() {
|
||||
ThreadPoolExecutorFactoryBean executor() {
|
||||
return new ThreadPoolExecutorFactoryBean();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -22,7 +22,7 @@ import org.springframework.core.task.AsyncListenableTaskExecutor;
|
|||
* @author Juergen Hoeller
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public class ThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
class ThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
|
||||
|
||||
@Override
|
||||
protected AsyncListenableTaskExecutor buildExecutor() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.scheduling.concurrent;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -37,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests {
|
||||
|
@ -53,8 +53,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
|
||||
|
||||
@Test
|
||||
public void executeFailingRunnableWithErrorHandler() {
|
||||
TestTask task = new TestTask(0);
|
||||
void executeFailingRunnableWithErrorHandler() {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
TestErrorHandler errorHandler = new TestErrorHandler(1);
|
||||
scheduler.setErrorHandler(errorHandler);
|
||||
scheduler.execute(task);
|
||||
|
@ -63,8 +63,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingRunnableWithErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(0);
|
||||
void submitFailingRunnableWithErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
TestErrorHandler errorHandler = new TestErrorHandler(1);
|
||||
scheduler.setErrorHandler(errorHandler);
|
||||
Future<?> future = scheduler.submit(task);
|
||||
|
@ -75,8 +75,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void submitFailingCallableWithErrorHandler() throws Exception {
|
||||
TestCallable task = new TestCallable(0);
|
||||
void submitFailingCallableWithErrorHandler() throws Exception {
|
||||
TestCallable task = new TestCallable(this.testName, 0);
|
||||
TestErrorHandler errorHandler = new TestErrorHandler(1);
|
||||
scheduler.setErrorHandler(errorHandler);
|
||||
Future<String> future = scheduler.submit(task);
|
||||
|
@ -87,8 +87,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void scheduleOneTimeTask() throws Exception {
|
||||
TestTask task = new TestTask(1);
|
||||
void scheduleOneTimeTask() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 1);
|
||||
Future<?> future = scheduler.schedule(task, new Date());
|
||||
Object result = future.get(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNull();
|
||||
|
@ -97,17 +97,16 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void scheduleOneTimeFailingTaskWithoutErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(0);
|
||||
void scheduleOneTimeFailingTaskWithoutErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
Future<?> future = scheduler.schedule(task, new Date());
|
||||
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
|
||||
future.get(1000, TimeUnit.MILLISECONDS));
|
||||
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() -> future.get(1000, TimeUnit.MILLISECONDS));
|
||||
assertThat(future.isDone()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleOneTimeFailingTaskWithErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(0);
|
||||
void scheduleOneTimeFailingTaskWithErrorHandler() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 0);
|
||||
TestErrorHandler errorHandler = new TestErrorHandler(1);
|
||||
scheduler.setErrorHandler(errorHandler);
|
||||
Future<?> future = scheduler.schedule(task, new Date());
|
||||
|
@ -118,8 +117,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void scheduleTriggerTask() throws Exception {
|
||||
TestTask task = new TestTask(3);
|
||||
void scheduleTriggerTask() throws Exception {
|
||||
TestTask task = new TestTask(this.testName, 3);
|
||||
Future<?> future = scheduler.schedule(task, new TestTrigger(3));
|
||||
Object result = future.get(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNull();
|
||||
|
@ -128,8 +127,8 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
@Test
|
||||
public void scheduleMultipleTriggerTasks() throws Exception {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
void scheduleMultipleTriggerTasks() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
scheduleTriggerTask();
|
||||
}
|
||||
}
|
||||
|
@ -158,52 +157,6 @@ public class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutor
|
|||
}
|
||||
|
||||
|
||||
private static class TestTask implements Runnable {
|
||||
|
||||
private final int expectedRunCount;
|
||||
|
||||
private final AtomicInteger actualRunCount = new AtomicInteger();
|
||||
|
||||
private final CountDownLatch latch;
|
||||
|
||||
private Thread lastThread;
|
||||
|
||||
TestTask(int expectedRunCount) {
|
||||
this.expectedRunCount = expectedRunCount;
|
||||
this.latch = new CountDownLatch(expectedRunCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
lastThread = Thread.currentThread();
|
||||
if (actualRunCount.incrementAndGet() > expectedRunCount) {
|
||||
throw new RuntimeException("intentional test failure");
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestCallable implements Callable<String> {
|
||||
|
||||
private final int expectedRunCount;
|
||||
|
||||
private final AtomicInteger actualRunCount = new AtomicInteger();
|
||||
|
||||
TestCallable(int expectedRunCount) {
|
||||
this.expectedRunCount = expectedRunCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (actualRunCount.incrementAndGet() > expectedRunCount) {
|
||||
throw new RuntimeException("intentional test failure");
|
||||
}
|
||||
return Thread.currentThread().getName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestErrorHandler implements ErrorHandler {
|
||||
|
||||
private final CountDownLatch latch;
|
||||
|
|
Loading…
Reference in New Issue