Skip to content

Commit

Permalink
Backport some fixes and cleanups for DefaultPromiseTest (netty#11600)
Browse files Browse the repository at this point in the history
Motivation:
These cleanups were done in another PR but were not directly related to that PR.
This extracts those changes and backports them to 4.1.

Modification:
* Remove the use of mocking in DefaultPromiseTest.
* Fix a few warnings.
* Make `testStackOverFlowChainedFuturesB` test with the right listener chain.

Result:
Cleaner code.
  • Loading branch information
chrisvest authored Aug 19, 2021
1 parent 9f4e155 commit e9893ad
Showing 1 changed file with 78 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.function.Executable;
import org.mockito.Mockito;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
Expand All @@ -37,17 +37,15 @@
import java.util.concurrent.atomic.AtomicInteger;

import static java.lang.Math.max;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.lessThan;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

@SuppressWarnings("unchecked")
public class DefaultPromiseTest {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultPromiseTest.class);
private static int stackOverflowDepth;
Expand All @@ -62,6 +60,7 @@ public static void beforeClass() {
}
}

@SuppressWarnings("InfiniteRecursion")
private static void findStackOverflowDepth() {
++stackOverflowDepth;
findStackOverflowDepth();
Expand All @@ -71,38 +70,99 @@ private static int stackOverflowTestDepth() {
return max(stackOverflowDepth << 1, stackOverflowDepth);
}

private static class RejectingEventExecutor extends AbstractEventExecutor {
@Override
public boolean isShuttingDown() {
return false;
}

@Override
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
return null;
}

@Override
public Future<?> terminationFuture() {
return null;
}

@Override
public void shutdown() {
}

@Override
public boolean isShutdown() {
return false;
}

@Override
public boolean isTerminated() {
return false;
}

@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return false;
}

@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return fail("Cannot schedule commands");
}

@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return fail("Cannot schedule commands");
}

@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return fail("Cannot schedule commands");
}

@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,
TimeUnit unit) {
return fail("Cannot schedule commands");
}

@Override
public boolean inEventLoop(Thread thread) {
return false;
}

@Override
public void execute(Runnable command) {
fail("Cannot schedule commands");
}
}

@Test
public void testCancelDoesNotScheduleWhenNoListeners() {
EventExecutor executor = Mockito.mock(EventExecutor.class);
Mockito.when(executor.inEventLoop()).thenReturn(false);
EventExecutor executor = new RejectingEventExecutor();

Promise<Void> promise = new DefaultPromise<Void>(executor);
assertTrue(promise.cancel(false));
Mockito.verify(executor, Mockito.never()).execute(Mockito.any(Runnable.class));
assertTrue(promise.isCancelled());
}

@Test
public void testSuccessDoesNotScheduleWhenNoListeners() {
EventExecutor executor = Mockito.mock(EventExecutor.class);
Mockito.when(executor.inEventLoop()).thenReturn(false);
EventExecutor executor = new RejectingEventExecutor();

Object value = new Object();
Promise<Object> promise = new DefaultPromise<Object>(executor);
promise.setSuccess(value);
Mockito.verify(executor, Mockito.never()).execute(Mockito.any(Runnable.class));
assertSame(value, promise.getNow());
}

@Test
public void testFailureDoesNotScheduleWhenNoListeners() {
EventExecutor executor = Mockito.mock(EventExecutor.class);
Mockito.when(executor.inEventLoop()).thenReturn(false);
EventExecutor executor = new RejectingEventExecutor();

Exception cause = new Exception();
Promise<Void> promise = new DefaultPromise<Void>(executor);
promise.setFailure(cause);
Mockito.verify(executor, Mockito.never()).execute(Mockito.any(Runnable.class));
assertSame(cause, promise.cause());
}

Expand Down Expand Up @@ -134,7 +194,7 @@ public void execute() throws Throwable {
public void testCancellationExceptionIsReturnedAsCause() {
final Promise<Void> promise = new DefaultPromise<Void>(ImmediateEventExecutor.INSTANCE);
assertTrue(promise.cancel(false));
assertThat(promise.cause(), instanceOf(CancellationException.class));
assertThat(promise.cause()).isInstanceOf(CancellationException.class);
}

@Test
Expand Down Expand Up @@ -293,7 +353,7 @@ public void run() {
promise.getKey().start();
final long start = System.nanoTime();
promise.getValue().awaitUninterruptibly(wait, TimeUnit.NANOSECONDS);
assertThat(System.nanoTime() - start, lessThan(wait));
assertThat(System.nanoTime() - start).isLessThan(wait);
}
} finally {
if (executor != null) {
Expand Down Expand Up @@ -386,11 +446,11 @@ private static void testStackOverFlowChainedFuturesB(int promiseChainLength, fin
executor.execute(new Runnable() {
@Override
public void run() {
testStackOverFlowChainedFuturesA(executor, p, latch);
testStackOverFlowChainedFuturesB(executor, p, latch);
}
});
} else {
testStackOverFlowChainedFuturesA(executor, p, latch);
testStackOverFlowChainedFuturesB(executor, p, latch);
}

assertTrue(latch.await(2, TimeUnit.SECONDS));
Expand Down

0 comments on commit e9893ad

Please sign in to comment.