diff --git a/servicetalk-loadbalancer/build.gradle b/servicetalk-loadbalancer/build.gradle index a36a4dad27..03fdbdf3e7 100644 --- a/servicetalk-loadbalancer/build.gradle +++ b/servicetalk-loadbalancer/build.gradle @@ -31,7 +31,9 @@ dependencies { testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-concurrent-test-internal") testImplementation project(":servicetalk-test-resources") - testImplementation "junit:junit:$junitVersion" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" + + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" } diff --git a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/EagerRoundRobinLoadBalancerTest.java b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/EagerRoundRobinLoadBalancerTest.java index ee51ebd05c..8ff00f19a7 100644 --- a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/EagerRoundRobinLoadBalancerTest.java +++ b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/EagerRoundRobinLoadBalancerTest.java @@ -15,7 +15,7 @@ */ package io.servicetalk.loadbalancer; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION; import static org.hamcrest.MatcherAssert.assertThat; @@ -25,10 +25,10 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -public class EagerRoundRobinLoadBalancerTest extends RoundRobinLoadBalancerTest { +class EagerRoundRobinLoadBalancerTest extends RoundRobinLoadBalancerTest { @Test - public void duplicateEventsAreIgnored() { + void duplicateEventsAreIgnored() { assertThat(lb.usedAddresses(), is(empty())); sendServiceDiscoveryEvents(upEvent("address-1")); @@ -43,7 +43,7 @@ public void duplicateEventsAreIgnored() { } @Test - public void handleDiscoveryEvents() { + void handleDiscoveryEvents() { assertAddresses(lb.usedAddresses(), EMPTY_ARRAY); sendServiceDiscoveryEvents(upEvent("address-1")); @@ -79,7 +79,7 @@ public void handleDiscoveryEvents() { } @Test - public void hostDownGracefullyClosesConnections() throws Exception { + void hostDownGracefullyClosesConnections() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); TestLoadBalancedConnection host1Conn1 = lb.selectConnection(alwaysNewConnectionFilter()).toFuture().get(); diff --git a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/LingeringRoundRobinLoadBalancerTest.java b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/LingeringRoundRobinLoadBalancerTest.java index 5c79fb7b02..d7a96b3f3e 100644 --- a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/LingeringRoundRobinLoadBalancerTest.java +++ b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/LingeringRoundRobinLoadBalancerTest.java @@ -20,7 +20,7 @@ import io.servicetalk.concurrent.api.Executor; import io.servicetalk.concurrent.api.Executors; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -34,21 +34,21 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -public class LingeringRoundRobinLoadBalancerTest extends RoundRobinLoadBalancerTest { +class LingeringRoundRobinLoadBalancerTest extends RoundRobinLoadBalancerTest { @Test - public void hostDownDoesntCloseConnectionCloseLB() throws Exception { + void hostDownDoesntCloseConnectionCloseLB() throws Exception { hostDownDoesntCloseConnection(false); } @Test - public void hostDownDoesntCloseConnectionCloseLBGracefully() throws Exception { + void hostDownDoesntCloseConnectionCloseLBGracefully() throws Exception { hostDownDoesntCloseConnection(true); } @@ -73,7 +73,7 @@ private void hostDownDoesntCloseConnection(boolean gracefulClosure) throws Excep } @Test - public void closedConnectionRemovesExpiredHost() throws Exception { + void closedConnectionRemovesExpiredHost() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); final Predicate connectionFilter = alwaysNewConnectionFilter(); @@ -93,7 +93,7 @@ public void closedConnectionRemovesExpiredHost() throws Exception { // Concurrency test, worth running ~10K times to spot concurrency issues. @Test - public void closureOfLastConnectionDoesntRaceWithNewAvailableEvent() throws Exception { + void closureOfLastConnectionDoesntRaceWithNewAvailableEvent() throws Exception { Executor executor = Executors.newFixedSizeExecutor(1); try { sendServiceDiscoveryEvents(upEvent("address-1")); @@ -116,7 +116,7 @@ public void closureOfLastConnectionDoesntRaceWithNewAvailableEvent() throws Exce // Concurrency test, worth running >10K times to spot concurrency issues. @Test - public void expiringAHostDoesntRaceWithConnectionAdding() throws Exception { + void expiringAHostDoesntRaceWithConnectionAdding() throws Exception { Executor executor = Executors.newFixedSizeExecutor(1); try { sendServiceDiscoveryEvents(upEvent("address-1")); @@ -167,7 +167,7 @@ public void expiringAHostDoesntRaceWithConnectionAdding() throws Exception { // Concurrency test, worth running >10K times to spot concurrency issues. @Test - public void expiringHostWhileConnectionsClose() throws Exception { + void expiringHostWhileConnectionsClose() throws Exception { Executor executor = Executors.newFixedSizeExecutor(1); try { sendServiceDiscoveryEvents(upEvent("address-1")); @@ -192,7 +192,7 @@ public void expiringHostWhileConnectionsClose() throws Exception { } @Test - public void closedConnectionDoesntRemoveActiveHost() throws Exception { + void closedConnectionDoesntRemoveActiveHost() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); final Predicate connectionFilter = alwaysNewConnectionFilter(); @@ -206,7 +206,7 @@ public void closedConnectionDoesntRemoveActiveHost() throws Exception { } @Test - public void handleDiscoveryEventsForExpiredHostBecomingAvailable() throws Exception { + void handleDiscoveryEventsForExpiredHostBecomingAvailable() throws Exception { assertAddresses(lb.usedAddresses(), EMPTY_ARRAY); sendServiceDiscoveryEvents(upEvent("address-1")); @@ -233,7 +233,7 @@ public void handleDiscoveryEventsForExpiredHostBecomingAvailable() throws Except } @Test - public void handleDiscoveryEventsForConnectedHosts() throws Exception { + void handleDiscoveryEventsForConnectedHosts() throws Exception { assertThat(lb.usedAddresses(), is(empty())); final Predicate connectionFilter = alwaysNewConnectionFilter(); @@ -276,7 +276,7 @@ public void handleDiscoveryEventsForConnectedHosts() throws Exception { } @Test - public void handleDiscoveryEventsForNotConnectedHosts() { + void handleDiscoveryEventsForNotConnectedHosts() { assertThat(lb.usedAddresses(), is(empty())); sendServiceDiscoveryEvents(upEvent("address-1")); diff --git a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancerTest.java b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancerTest.java index eda50e7991..c70bb96066 100644 --- a/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancerTest.java +++ b/servicetalk-loadbalancer/src/test/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancerTest.java @@ -26,7 +26,7 @@ import io.servicetalk.concurrent.PublisherSource.Subscription; import io.servicetalk.concurrent.api.Completable; import io.servicetalk.concurrent.api.Executor; -import io.servicetalk.concurrent.api.ExecutorRule; +import io.servicetalk.concurrent.api.ExecutorExtension; import io.servicetalk.concurrent.api.LegacyTestSingle; import io.servicetalk.concurrent.api.ListenableAsyncCloseable; import io.servicetalk.concurrent.api.Publisher; @@ -35,17 +35,14 @@ import io.servicetalk.concurrent.api.TestPublisher; import io.servicetalk.concurrent.api.TestSubscription; import io.servicetalk.concurrent.internal.DeliberateException; -import io.servicetalk.concurrent.internal.ServiceTalkTestTimeout; import io.servicetalk.concurrent.test.internal.TestSingleSubscriber; import io.servicetalk.transport.api.TransportObserver; import org.hamcrest.Matcher; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.Timeout; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import java.time.Duration; import java.util.AbstractMap; @@ -97,68 +94,62 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; abstract class RoundRobinLoadBalancerTest { - protected static final String[] EMPTY_ARRAY = new String[] {}; + static final String[] EMPTY_ARRAY = new String[] {}; - @Rule - public final Timeout timeout = new ServiceTalkTestTimeout(); + @RegisterExtension + final ExecutorExtension executor = ExecutorExtension.withTestExecutor(); - @Rule - public final ExpectedException thrown = ExpectedException.none(); - - @Rule - public final ExecutorRule executor = ExecutorRule.withTestExecutor(); - - protected final TestSingleSubscriber selectConnectionListener = + private final TestSingleSubscriber selectConnectionListener = new TestSingleSubscriber<>(); - protected final List connectionsCreated = new CopyOnWriteArrayList<>(); - protected final Queue connectionRealizers = new ConcurrentLinkedQueue<>(); + private final List connectionsCreated = new CopyOnWriteArrayList<>(); + private final Queue connectionRealizers = new ConcurrentLinkedQueue<>(); - protected final TestPublisher> serviceDiscoveryPublisher = new TestPublisher<>(); + final TestPublisher> serviceDiscoveryPublisher = new TestPublisher<>(); private DelegatingConnectionFactory connectionFactory = new DelegatingConnectionFactory(this::newRealizedConnectionSingle); - protected RoundRobinLoadBalancer lb; + RoundRobinLoadBalancer lb; - protected TestExecutor testExecutor; + private TestExecutor testExecutor; - protected static Predicate any() { + static Predicate any() { return __ -> true; } - protected Predicate alwaysNewConnectionFilter() { + Predicate alwaysNewConnectionFilter() { return cnx -> lb.usedAddresses().stream().noneMatch(addr -> addr.getValue().stream().anyMatch(cnx::equals)); } - protected RoundRobinLoadBalancer defaultLb() { + RoundRobinLoadBalancer defaultLb() { return newTestLoadBalancer(eagerConnectionShutdown()); } - protected RoundRobinLoadBalancer defaultLb( - DelegatingConnectionFactory connectionFactory) { + RoundRobinLoadBalancer defaultLb( + DelegatingConnectionFactory connectionFactory) { return newTestLoadBalancer(serviceDiscoveryPublisher, connectionFactory, eagerConnectionShutdown()); } protected abstract boolean eagerConnectionShutdown(); - @Before - public void initialize() { + @BeforeEach + void initialize() { testExecutor = executor.executor(); lb = defaultLb(); connectionsCreated.clear(); connectionRealizers.clear(); } - @After - public void closeLoadBalancer() throws Exception { + @AfterEach + void closeLoadBalancer() throws Exception { awaitIndefinitely(lb.closeAsync()); awaitIndefinitely(lb.onClose()); @@ -176,7 +167,7 @@ public void closeLoadBalancer() throws Exception { } @Test - public void streamEventJustClose() throws InterruptedException { + void streamEventJustClose() throws InterruptedException { CountDownLatch readyLatch = new CountDownLatch(1); CountDownLatch completeLatch = new CountDownLatch(1); lb.eventStream().afterOnComplete(completeLatch::countDown).firstOrElse(() -> { @@ -189,7 +180,7 @@ public void streamEventJustClose() throws InterruptedException { } @Test - public void streamEventReadyAndCompleteOnClose() throws InterruptedException { + void streamEventReadyAndCompleteOnClose() throws InterruptedException { CountDownLatch readyLatch = new CountDownLatch(1); CountDownLatch completeLatch = new CountDownLatch(1); AtomicReference causeRef = new AtomicReference<>(); @@ -227,14 +218,14 @@ public void onComplete() { } @Test - public void unknownAddressIsRemoved() { + void unknownAddressIsRemoved() { assertAddresses(lb.usedAddresses(), EMPTY_ARRAY); sendServiceDiscoveryEvents(downEvent("address-1")); assertAddresses(lb.usedAddresses(), EMPTY_ARRAY); } @Test - public void noServiceDiscoveryEvent() { + void noServiceDiscoveryEvent() { toSource(lb.selectConnection(any())).subscribe(selectConnectionListener); assertThat(selectConnectionListener.awaitOnError(), instanceOf(NoAvailableHostException.class)); @@ -242,14 +233,14 @@ public void noServiceDiscoveryEvent() { } @Test - public void selectStampedeUnsaturableConnection() throws Exception { + void selectStampedeUnsaturableConnection() throws Exception { serviceDiscoveryPublisher.onComplete(); testSelectStampede(any()); } @Test - public void selectStampedeSaturableConnection() throws Exception { + void selectStampedeSaturableConnection() throws Exception { serviceDiscoveryPublisher.onComplete(); testSelectStampede(newSaturableConnectionFilter()); @@ -314,9 +305,8 @@ private void testSelectStampede(final Predicate sele assertThat(connectionsCreated, hasSize(both(greaterThan(0)).and(lessThanOrEqualTo(100)))); } - @SuppressWarnings("unchecked") @Test - public void roundRobining() throws Exception { + void roundRobining() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); sendServiceDiscoveryEvents(upEvent("address-2")); final List connections = awaitIndefinitely((lb.selectConnection(any()) @@ -336,7 +326,7 @@ public void roundRobining() throws Exception { } @Test - public void closedConnectionPruning() throws Exception { + void closedConnectionPruning() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); final TestLoadBalancedConnection connection = awaitIndefinitely(lb.selectConnection(any())); @@ -354,40 +344,38 @@ public void closedConnectionPruning() throws Exception { } @Test - public void connectionFactoryErrorPropagation() throws Exception { + void connectionFactoryErrorPropagation() { serviceDiscoveryPublisher.onComplete(); - thrown.expect(instanceOf(ExecutionException.class)); - thrown.expectCause(instanceOf(DeliberateException.class)); connectionFactory = new DelegatingConnectionFactory(__ -> failed(DELIBERATE_EXCEPTION)); lb = defaultLb(connectionFactory); sendServiceDiscoveryEvents(upEvent("address-1")); - awaitIndefinitely(lb.selectConnection(any())); + + ExecutionException ex = assertThrows(ExecutionException.class, + () -> awaitIndefinitely(lb.selectConnection(any()))); + assertThat(ex.getCause(), is(instanceOf(DeliberateException.class))); } @Test - public void earlyFailsAfterClose() throws Exception { - thrown.expect(instanceOf(ExecutionException.class)); - thrown.expectCause(instanceOf(IllegalStateException.class)); - + void earlyFailsAfterClose() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); awaitIndefinitely(lb.closeAsync()); - try { - awaitIndefinitely(lb.selectConnection(any())); - } finally { - assertThat(connectionsCreated, is(empty())); - } + ExecutionException ex = assertThrows(ExecutionException.class, + () -> awaitIndefinitely(lb.selectConnection(any()))); + assertThat(ex.getCause(), is(instanceOf(IllegalStateException.class))); + + assertThat(connectionsCreated, is(empty())); } @Test - public void closeClosesConnectionFactory() throws Exception { + void closeClosesConnectionFactory() throws Exception { awaitIndefinitely(lb.closeAsync()); - assertTrue("ConnectionFactory not closed.", connectionFactory.isClosed()); + assertTrue(connectionFactory.isClosed(), "ConnectionFactory not closed."); } @Test - public void newConnectionIsClosedWhenSelectorRejects() throws Exception { + void newConnectionIsClosedWhenSelectorRejects() throws Exception { sendServiceDiscoveryEvents(upEvent("address-1")); try { awaitIndefinitely(lb.selectConnection(__ -> false)); @@ -403,7 +391,7 @@ public void newConnectionIsClosedWhenSelectorRejects() throws Exception { } @Test - public void unhealthyHostTakenOutOfPoolForSelection() throws Exception { + void unhealthyHostTakenOutOfPoolForSelection() throws Exception { serviceDiscoveryPublisher.onComplete(); final Single properConnection = newRealizedConnectionSingle("address-1"); @@ -446,7 +434,7 @@ public void unhealthyHostTakenOutOfPoolForSelection() throws Exception { } @Test - public void disabledHealthCheckDoesntRun() throws Exception { + void disabledHealthCheckDoesntRun() throws Exception { serviceDiscoveryPublisher.onComplete(); final Single properConnection = newRealizedConnectionSingle("address-1"); @@ -484,7 +472,7 @@ public void disabledHealthCheckDoesntRun() throws Exception { } @Test - public void hostUnhealthyIsHealthChecked() throws Exception { + void hostUnhealthyIsHealthChecked() throws Exception { serviceDiscoveryPublisher.onComplete(); final Single properConnection = newRealizedConnectionSingle("address-1"); final int timeAdvancementsTillHealthy = 3; @@ -516,7 +504,7 @@ public void hostUnhealthyIsHealthChecked() throws Exception { // Concurrency test, run multiple times (at least 1000). @Test - public void hostUnhealthyDoesntRaceToRunHealthCheck() throws Exception { + void hostUnhealthyDoesntRaceToRunHealthCheck() throws Exception { serviceDiscoveryPublisher.onComplete(); final Single properConnection = newRealizedConnectionSingle("address-1"); @@ -578,8 +566,7 @@ public void hostUnhealthyDoesntRaceToRunHealthCheck() throws Exception { assertThat(selectedConnection, equalTo(properConnection.toFuture().get())); } - @SuppressWarnings("unchecked") - protected void sendServiceDiscoveryEvents(final ServiceDiscovererEvent... events) { + void sendServiceDiscoveryEvents(final ServiceDiscovererEvent... events) { sendServiceDiscoveryEvents(serviceDiscoveryPublisher, events); } @@ -589,22 +576,22 @@ private void sendServiceDiscoveryEvents(TestPublisher(address, true); } - protected static ServiceDiscovererEvent downEvent(final String address) { + static ServiceDiscovererEvent downEvent(final String address) { return new DefaultServiceDiscovererEvent<>(address, false); } - protected RoundRobinLoadBalancer newTestLoadBalancer( - boolean eagerConnectionShutdown) { + RoundRobinLoadBalancer newTestLoadBalancer( + boolean eagerConnectionShutdown) { return newTestLoadBalancer(serviceDiscoveryPublisher, connectionFactory, eagerConnectionShutdown); } - protected RoundRobinLoadBalancer newTestLoadBalancer( - final TestPublisher> serviceDiscoveryPublisher, - final DelegatingConnectionFactory connectionFactory, final boolean eagerConnectionShutdown) { + RoundRobinLoadBalancer newTestLoadBalancer( + final TestPublisher> serviceDiscoveryPublisher, + final DelegatingConnectionFactory connectionFactory, final boolean eagerConnectionShutdown) { return (RoundRobinLoadBalancer) new RoundRobinLoadBalancerFactory.Builder() .eagerConnectionShutdown(eagerConnectionShutdown) @@ -614,8 +601,8 @@ protected RoundRobinLoadBalancer newTestLoad } @SafeVarargs - protected static void assertConnectionCount( - Iterable addresses, Map.Entry... addressAndConnCount) { + static void assertConnectionCount( + Iterable addresses, Map.Entry... addressAndConnCount) { @SuppressWarnings("unchecked") final Matcher[] args = (Matcher[]) Arrays.stream(addressAndConnCount) .map(ac -> both(hasProperty("key", is(ac.getKey()))) @@ -627,11 +614,11 @@ protected static void assertConnectionCount( assertThat(addresses, iterableMatcher); } - protected Map.Entry connectionsCount(String addr, int count) { + Map.Entry connectionsCount(String addr, int count) { return new AbstractMap.SimpleImmutableEntry<>(addr, count); } - protected void assertAddresses(Iterable addresses, String... address) { + void assertAddresses(Iterable addresses, String... address) { @SuppressWarnings("unchecked") final Matcher[] args = (Matcher[]) Arrays.stream(address) .map(a -> hasProperty("key", is(a))) @@ -679,11 +666,11 @@ private static Predicate newSaturableConnectionFilte }; } - protected interface TestLoadBalancedConnection extends LoadBalancedConnection { + interface TestLoadBalancedConnection extends LoadBalancedConnection { String address(); } - protected static class DelegatingConnectionFactory implements + static class DelegatingConnectionFactory implements ConnectionFactory { private final Function> connectionFactory; @@ -713,14 +700,14 @@ boolean isClosed() { } } - protected static class UnhealthyHostConnectionFactory { + static class UnhealthyHostConnectionFactory { private final String failingHost; private final AtomicInteger momentInTime = new AtomicInteger(); final AtomicInteger requests = new AtomicInteger(); final Single properConnection; final List> connections; - Function> factory = + final Function> factory = new Function>() { @Override