From d5592d8fe62ec88e202ace61414233a730b48367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?TingI=C4=81u=20=22Ting=22=20K=C3=AC?= Date: Tue, 18 Jun 2024 18:20:14 +0800 Subject: [PATCH] KAFKA-16921 [5/N] Migrate test of connect module to Junit5 (Runtime subpackage) (#16350) Reviewers: Chia-Ping Tsai --- .../ConnectProtocolCompatibilityTest.java | 6 +- .../distributed/DistributedConfigTest.java | 25 +- .../distributed/DistributedHerderTest.java | 223 +++++---- .../IncrementalCooperativeAssignorTest.java | 335 ++++++------- .../WorkerCoordinatorIncrementalTest.java | 162 +++--- .../distributed/WorkerCoordinatorTest.java | 107 ++-- .../distributed/WorkerGroupMemberTest.java | 21 +- .../runtime/errors/ErrorReporterTest.java | 29 +- .../RetryWithToleranceOperatorTest.java | 27 +- .../WorkerErrantRecordReporterTest.java | 17 +- .../health/ConnectClusterStateImplTest.java | 29 +- .../isolation/DelegatingClassLoaderTest.java | 19 +- .../runtime/isolation/PluginDescTest.java | 20 +- .../runtime/isolation/PluginScannerTest.java | 162 +++--- .../runtime/isolation/PluginUtilsTest.java | 74 ++- .../runtime/isolation/PluginsTest.java | 38 +- .../isolation/SynchronizationTest.java | 34 +- .../runtime/rest/ConnectRestServerTest.java | 69 +-- .../rest/InternalRequestSignatureTest.java | 39 +- .../connect/runtime/rest/RestClientTest.java | 469 +++++++++--------- .../runtime/rest/RestServerConfigTest.java | 12 +- .../rest/entities/ConnectorOffsetsTest.java | 4 +- .../rest/entities/ConnectorTypeTest.java | 8 +- .../entities/CreateConnectorRequestTest.java | 6 +- .../runtime/rest/entities/PluginInfoTest.java | 2 +- .../ConnectorPluginsResourceTest.java | 23 +- .../resources/ConnectorsResourceTest.java | 40 +- .../InternalConnectResourceTest.java | 19 +- .../rest/resources/LoggingResourceTest.java | 21 +- .../rest/resources/RootResourceTest.java | 17 +- .../runtime/rest/util/SSLUtilsTest.java | 88 ++-- .../standalone/StandaloneConfigTest.java | 4 +- .../standalone/StandaloneHerderTest.java | 412 ++++++++------- 33 files changed, 1325 insertions(+), 1236 deletions(-) diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/ConnectProtocolCompatibilityTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/ConnectProtocolCompatibilityTest.java index 38084383e29..e2b34af6855 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/ConnectProtocolCompatibilityTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/ConnectProtocolCompatibilityTest.java @@ -17,7 +17,7 @@ package org.apache.kafka.connect.runtime.distributed; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.nio.ByteBuffer; import java.util.Arrays; @@ -25,8 +25,8 @@ import java.util.Collections; import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V1; import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V2; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; public class ConnectProtocolCompatibilityTest { private static final String LEADER = "leader"; diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedConfigTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedConfigTest.java index c7fc0d8299a..4a10fe482d0 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedConfigTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedConfigTest.java @@ -20,9 +20,11 @@ package org.apache.kafka.connect.runtime.distributed; import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.security.auth.SecurityProtocol; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import javax.crypto.KeyGenerator; import javax.crypto.Mac; @@ -43,18 +45,19 @@ import static org.apache.kafka.connect.runtime.distributed.DistributedConfig.GRO import static org.apache.kafka.connect.runtime.distributed.DistributedConfig.INTER_WORKER_KEY_GENERATION_ALGORITHM_CONFIG; import static org.apache.kafka.connect.runtime.distributed.DistributedConfig.INTER_WORKER_SIGNATURE_ALGORITHM_CONFIG; import static org.apache.kafka.connect.runtime.distributed.DistributedConfig.INTER_WORKER_VERIFICATION_ALGORITHMS_CONFIG; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class DistributedConfigTest { public Map configs() { @@ -148,7 +151,7 @@ public class DistributedConfigTest { Set supportedAlgorithms = DistributedConfig.supportedAlgorithms(type); Set unsupportedAlgorithms = new HashSet<>(Arrays.asList(expectedAlgorithms)); unsupportedAlgorithms.removeAll(supportedAlgorithms); - assertEquals(type + " algorithms were found that should be supported by this JVM but are not", Collections.emptySet(), unsupportedAlgorithms); + assertEquals(Collections.emptySet(), unsupportedAlgorithms, type + " algorithms were found that should be supported by this JVM but are not"); } @Test diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedHerderTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedHerderTest.java index 028e5202bf5..a64539e8f3a 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedHerderTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/DistributedHerderTest.java @@ -72,13 +72,15 @@ import org.apache.kafka.connect.util.Callback; import org.apache.kafka.connect.util.ConnectorTaskId; import org.apache.kafka.connect.util.FutureCallback; import org.apache.kafka.connect.util.Stage; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import javax.crypto.SecretKey; @@ -122,11 +124,11 @@ import static org.apache.kafka.connect.runtime.distributed.DistributedConfig.INT import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V1; import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V2; import static org.apache.kafka.connect.source.SourceTask.TransactionBoundary.CONNECTOR; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +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.junit.jupiter.api.Assertions.assertInstanceOf; import static org.mockito.AdditionalMatchers.leq; import static org.mockito.ArgumentMatchers.any; @@ -147,7 +149,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) @SuppressWarnings("unchecked") public class DistributedHerderTest { private static final Map HERDER_CONFIG = new HashMap<>(); @@ -301,12 +304,11 @@ public class DistributedHerderTest { private final SampleConnectorClientConfigOverridePolicy noneConnectorClientConfigOverridePolicy = new SampleConnectorClientConfigOverridePolicy(); - @Before + @BeforeEach public void setUp() throws Exception { time = new MockTime(); metrics = new MockConnectMetrics(time); - when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); - AutoCloseable uponShutdown = () -> shutdownCalled.countDown(); + AutoCloseable uponShutdown = shutdownCalled::countDown; // Default to the old protocol unless specified otherwise connectProtocolVersion = CONNECT_PROTOCOL_V0; @@ -319,11 +321,9 @@ public class DistributedHerderTest { rebalanceListener = herder.new RebalanceListener(time); conn1SinkConfig = new SinkConnectorConfig(plugins, CONN1_CONFIG); conn1SinkConfigUpdated = new SinkConnectorConfig(plugins, CONN1_CONFIG_UPDATED); - - when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); } - @After + @AfterEach public void tearDown() { if (metrics != null) metrics.stop(); if (herderExecutor != null) { @@ -333,10 +333,12 @@ public class DistributedHerderTest { } @Test - public void testJoinAssignment() throws Exception { + public void testJoinAssignment() { // Join group and get assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, singletonList(CONN1), singletonList(TASK1)); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -357,10 +359,12 @@ public class DistributedHerderTest { } @Test - public void testRebalance() throws Exception { + public void testRebalance() { // Join group and get assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, singletonList(CONN1), singletonList(TASK1)); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -401,12 +405,14 @@ public class DistributedHerderTest { } @Test - public void testIncrementalCooperativeRebalanceForNewMember() throws Exception { + public void testIncrementalCooperativeRebalanceForNewMember() { connectProtocolVersion = CONNECT_PROTOCOL_V1; // Join group. First rebalance contains revocations from other members. For the new // member the assignment should be empty when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V1); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList()); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -478,7 +484,7 @@ public class DistributedHerderTest { } @Test - public void testIncrementalCooperativeRebalanceWithDelay() throws Exception { + public void testIncrementalCooperativeRebalanceWithDelay() { connectProtocolVersion = CONNECT_PROTOCOL_V1; // Join group. First rebalance contains some assignments but also a delay, because a // member was detected missing @@ -486,6 +492,8 @@ public class DistributedHerderTest { when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V1); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(Collections.emptyList(), Collections.emptyList(), ConnectProtocol.Assignment.NO_ERROR, 1, Collections.emptyList(), singletonList(TASK2), @@ -530,10 +538,12 @@ public class DistributedHerderTest { } @Test - public void testRebalanceFailedConnector() throws Exception { + public void testRebalanceFailedConnector() { // Join group and get assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, singletonList(CONN1), singletonList(TASK1)); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -574,16 +584,20 @@ public class DistributedHerderTest { } @Test - public void testRevoke() throws TimeoutException { + public void testRevoke() { + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); revokeAndReassign(false); } @Test - public void testIncompleteRebalanceBeforeRevoke() throws TimeoutException { + public void testIncompleteRebalanceBeforeRevoke() { + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); revokeAndReassign(true); } - public void revokeAndReassign(boolean incompleteRebalance) throws TimeoutException { + public void revokeAndReassign(boolean incompleteRebalance) { connectProtocolVersion = CONNECT_PROTOCOL_V1; int configOffset = 1; @@ -681,9 +695,10 @@ public class DistributedHerderTest { } @Test - public void testCreateConnector() throws Exception { + public void testCreateConnector() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -736,9 +751,10 @@ public class DistributedHerderTest { } @Test - public void testCreateConnectorWithInitialState() throws Exception { + public void testCreateConnectorWithInitialState() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -843,7 +859,7 @@ public class DistributedHerderTest { } @Test - public void testCreateConnectorFailedValidation() throws Exception { + public void testCreateConnectorFailedValidation() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); @@ -933,7 +949,7 @@ public class DistributedHerderTest { } @Test - public void testCreateConnectorAlreadyExists() throws Exception { + public void testCreateConnectorAlreadyExists() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); @@ -976,7 +992,8 @@ public class DistributedHerderTest { } @Test - public void testDestroyConnector() throws Exception { + public void testDestroyConnector() { + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); // Start with one connector @@ -1045,6 +1062,7 @@ public class DistributedHerderTest { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); expectRebalance(1, singletonList(CONN1), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -1077,7 +1095,7 @@ public class DistributedHerderTest { } @Test - public void testRestartUnknownConnector() throws Exception { + public void testRestartUnknownConnector() { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1101,7 +1119,7 @@ public class DistributedHerderTest { } @Test - public void testRestartConnectorRedirectToLeader() throws Exception { + public void testRestartConnectorRedirectToLeader() { // get the initial assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1125,7 +1143,7 @@ public class DistributedHerderTest { } @Test - public void testRestartConnectorRedirectToOwner() throws Exception { + public void testRestartConnectorRedirectToOwner() { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1160,7 +1178,7 @@ public class DistributedHerderTest { } @Test - public void testRestartConnectorAndTasksUnknownConnector() throws Exception { + public void testRestartConnectorAndTasksUnknownConnector() { String connectorName = "UnknownConnector"; RestartRequest restartRequest = new RestartRequest(connectorName, false, true); @@ -1189,7 +1207,7 @@ public class DistributedHerderTest { } @Test - public void testRestartConnectorAndTasksNotLeader() throws Exception { + public void testRestartConnectorAndTasksNotLeader() { // get the initial assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1214,7 +1232,7 @@ public class DistributedHerderTest { } @Test - public void testRestartConnectorAndTasksUnknownStatus() throws Exception { + public void testRestartConnectorAndTasksUnknownStatus() { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1345,6 +1363,7 @@ public class DistributedHerderTest { when(herder.assignment.connectors()).thenReturn(Collections.emptyList()); // But only one task is assigned to this worker when(herder.assignment.tasks()).thenReturn(Collections.singletonList(TASK0)); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); herder.configState = SNAPSHOT; @@ -1368,6 +1387,7 @@ public class DistributedHerderTest { when(restartPlan.shouldRestartConnector()).thenReturn(true); when(restartPlan.taskIdsToRestart()).thenReturn(Collections.singletonList(taskId)); when(restartPlan.totalTaskCount()).thenReturn(1); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); doReturn(Optional.of(restartPlan)).when(herder).buildRestartPlan(restartRequest); herder.assignment = mock(ExtendedAssignment.class); @@ -1405,6 +1425,7 @@ public class DistributedHerderTest { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), singletonList(TASK0), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -1429,7 +1450,7 @@ public class DistributedHerderTest { } @Test - public void testRestartUnknownTask() throws Exception { + public void testRestartUnknownTask() { // get the initial assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1451,7 +1472,7 @@ public class DistributedHerderTest { } @Test - public void testRestartTaskRedirectToLeader() throws Exception { + public void testRestartTaskRedirectToLeader() { // get the initial assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1474,7 +1495,7 @@ public class DistributedHerderTest { } @Test - public void testRestartTaskRedirectToOwner() throws Exception { + public void testRestartTaskRedirectToOwner() { // get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1519,8 +1540,9 @@ public class DistributedHerderTest { } @Test - public void testConnectorConfigAdded() throws Exception { + public void testConnectorConfigAdded() { // If a connector was added, we need to rebalance + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1531,7 +1553,7 @@ public class DistributedHerderTest { herder.tick(); // join // Checks for config updates and starts rebalance - expectConfigRefreshAndSnapshot(SNAPSHOT); + when(configBackingStore.snapshot()).thenReturn(SNAPSHOT); // Rebalance will be triggered when the new config is detected doNothing().when(member).requestRejoin(); @@ -1556,11 +1578,12 @@ public class DistributedHerderTest { } @Test - public void testConnectorConfigUpdate() throws Exception { + public void testConnectorConfigUpdate() { // Connector config can be applied without any rebalance when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); // join expectRebalance(1, singletonList(CONN1), Collections.emptyList()); @@ -1590,11 +1613,12 @@ public class DistributedHerderTest { } @Test - public void testConnectorConfigUpdateFailedTransformation() throws Exception { + public void testConnectorConfigUpdateFailedTransformation() { // Connector config can be applied without any rebalance when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); WorkerConfigTransformer configTransformer = mock(WorkerConfigTransformer.class); // join @@ -1647,11 +1671,12 @@ public class DistributedHerderTest { } @Test - public void testConnectorPaused() throws Exception { + public void testConnectorPaused() { // ensure that target state changes are propagated to the worker when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); // join expectRebalance(1, singletonList(CONN1), Collections.emptyList()); @@ -1686,9 +1711,10 @@ public class DistributedHerderTest { } @Test - public void testConnectorResumed() throws Exception { + public void testConnectorResumed() { when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); // start with the connector paused expectRebalance(1, singletonList(CONN1), Collections.emptyList()); @@ -1724,11 +1750,12 @@ public class DistributedHerderTest { } @Test - public void testConnectorStopped() throws Exception { + public void testConnectorStopped() { // ensure that target state changes are propagated to the worker when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); // join expectRebalance(1, singletonList(CONN1), Collections.emptyList()); @@ -1763,9 +1790,10 @@ public class DistributedHerderTest { } @Test - public void testUnknownConnectorPaused() throws Exception { + public void testUnknownConnectorPaused() { when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); // join expectRebalance(1, Collections.emptyList(), singletonList(TASK0)); @@ -1788,6 +1816,7 @@ public class DistributedHerderTest { @Test public void testStopConnector() throws Exception { + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1813,16 +1842,17 @@ public class DistributedHerderTest { herder.stopConnector(CONN1, cb); // external request herder.tick(); // continue - assertTrue("Callback should already have been invoked by herder", cb.isDone()); + assertTrue(cb.isDone(), "Callback should already have been invoked by herder"); cb.get(0, TimeUnit.MILLISECONDS); verifyNoMoreInteractions(worker, member, configBackingStore, statusBackingStore); } @Test - public void testStopConnectorNotLeader() throws Exception { + public void testStopConnectorNotLeader() { when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); // join as member (non-leader) expectRebalance(1, Collections.emptyList(), singletonList(TASK0)); @@ -1840,11 +1870,11 @@ public class DistributedHerderTest { herder.stopConnector(CONN1, cb); // external request herder.tick(); // continue - assertTrue("Callback should already have been invoked by herder", cb.isDone()); + assertTrue(cb.isDone(), "Callback should already have been invoked by herder"); ExecutionException e = assertThrows( - "Should not be able to handle request to stop connector when not leader", - ExecutionException.class, - () -> cb.get(0, TimeUnit.SECONDS) + ExecutionException.class, + () -> cb.get(0, TimeUnit.SECONDS), + "Should not be able to handle request to stop connector when not leader" ); assertInstanceOf(NotLeaderException.class, e.getCause()); @@ -1852,9 +1882,10 @@ public class DistributedHerderTest { } @Test - public void testStopConnectorFailToWriteTaskConfigs() throws Exception { + public void testStopConnectorFailToWriteTaskConfigs() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); // join as leader expectRebalance(1, Collections.emptyList(), singletonList(TASK0), true); @@ -1880,11 +1911,11 @@ public class DistributedHerderTest { herder.stopConnector(CONN1, cb); // external request herder.tick(); // continue - assertTrue("Callback should already have been invoked by herder", cb.isDone()); + assertTrue(cb.isDone(), "Callback should already have been invoked by herder"); ExecutionException e = assertThrows( - "Should not be able to handle request to stop connector when not leader", - ExecutionException.class, - () -> cb.get(0, TimeUnit.SECONDS) + ExecutionException.class, + () -> cb.get(0, TimeUnit.SECONDS), + "Should not be able to handle request to stop connector when not leader" ); assertEquals(e.getCause(), taskConfigsWriteException); @@ -1892,10 +1923,11 @@ public class DistributedHerderTest { } @Test - public void testConnectorPausedRunningTaskOnly() throws Exception { + public void testConnectorPausedRunningTaskOnly() { // even if we don't own the connector, we should still propagate target state // changes to the worker so that tasks will transition correctly + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1926,10 +1958,11 @@ public class DistributedHerderTest { } @Test - public void testConnectorResumedRunningTaskOnly() throws Exception { + public void testConnectorResumedRunningTaskOnly() { // even if we don't own the connector, we should still propagate target state // changes to the worker so that tasks will transition correctly + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -1951,7 +1984,6 @@ public class DistributedHerderTest { onStart.getValue().onCompletion(null, TargetState.PAUSED); return null; }).when(worker).setTargetState(eq(CONN1), eq(TargetState.STARTED), onStart.capture()); - expectExecuteTaskReconfiguration(false, null, null); configUpdateListener.onConnectorTargetStateChange(CONN1); // state changes to paused herder.tick(); // apply state change @@ -1966,6 +1998,7 @@ public class DistributedHerderTest { // Task config always requires rebalance when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); // join expectRebalance(-1, Collections.emptyList(), Collections.emptyList()); @@ -1985,7 +2018,6 @@ public class DistributedHerderTest { expectRebalance(Collections.emptyList(), Collections.emptyList(), ConnectProtocol.Assignment.NO_ERROR, 1, Collections.emptyList(), singletonList(TASK0)); - expectConfigRefreshAndSnapshot(SNAPSHOT); when(worker.startSourceTask(eq(TASK0), any(), any(), any(), eq(herder), eq(TargetState.STARTED))).thenReturn(true); herder.tick(); // do rebalance @@ -2000,6 +2032,8 @@ public class DistributedHerderTest { when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); when(configBackingStore.snapshot()).thenReturn(SNAPSHOT); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(Collections.emptyList(), Collections.emptyList(), ConnectProtocol.Assignment.CONFIG_MISMATCH, 1, "leader", "leaderUrl", Collections.emptyList(), @@ -2059,6 +2093,8 @@ public class DistributedHerderTest { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V1); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, singletonList(CONN1), singletonList(TASK1), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -2133,6 +2169,8 @@ public class DistributedHerderTest { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V1); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, singletonList(CONN1), singletonList(TASK1), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -2212,6 +2250,7 @@ public class DistributedHerderTest { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); @@ -2275,6 +2314,8 @@ public class DistributedHerderTest { @Test public void testPutConnectorConfig() throws Exception { + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); when(member.memberId()).thenReturn("leader"); expectRebalance(1, singletonList(CONN1), Collections.emptyList(), true); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); @@ -2398,7 +2439,6 @@ public class DistributedHerderTest { // Patch the connector config. - expectMemberEnsureActive(); expectRebalance(1, singletonList(CONN1), Collections.emptyList(), false); FutureCallback> patchCallback = new FutureCallback<>(); @@ -2411,8 +2451,8 @@ public class DistributedHerderTest { @Test public void testPatchConnectorConfig() throws Exception { + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); when(member.memberId()).thenReturn("leader"); - expectRebalance(1, singletonList(CONN1), Collections.emptyList(), true); when(statusBackingStore.connectors()).thenReturn(Collections.emptySet()); Map originalConnConfig = new HashMap<>(CONN1_CONFIG); @@ -2451,7 +2491,6 @@ public class DistributedHerderTest { patchedConnConfig.remove("foo2"); patchedConnConfig.put("foo3", "added"); - expectMemberEnsureActive(); expectRebalance(1, singletonList(CONN1), Collections.emptyList(), true); ArgumentCaptor> validateCallback = ArgumentCaptor.forClass(Callback.class); @@ -2476,7 +2515,7 @@ public class DistributedHerderTest { } @Test - public void testKeyRotationWhenWorkerBecomesLeader() throws Exception { + public void testKeyRotationWhenWorkerBecomesLeader() { long rotationTtlDelay = DistributedConfig.INTER_WORKER_KEY_TTL_MS_MS_DEFAULT; when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); @@ -2529,7 +2568,7 @@ public class DistributedHerderTest { } @Test - public void testKeyRotationDisabledWhenWorkerBecomesFollower() throws Exception { + public void testKeyRotationDisabledWhenWorkerBecomesFollower() { long rotationTtlDelay = DistributedConfig.INTER_WORKER_KEY_TTL_MS_MS_DEFAULT; when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); @@ -2710,7 +2749,7 @@ public class DistributedHerderTest { } @Test - public void testFailedToWriteSessionKey() throws Exception { + public void testFailedToWriteSessionKey() { // First tick -- after joining the group, we try to write a new // session key to the config topic, and fail when(member.memberId()).thenReturn("leader"); @@ -2878,6 +2917,7 @@ public class DistributedHerderTest { @Test public void testExternalZombieFencingRequestForAlreadyFencedConnector() throws Exception { + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); ClusterConfigState configState = exactlyOnceSnapshot( expectNewSessionKey(), TASK_CONFIGS_MAP, @@ -2890,6 +2930,7 @@ public class DistributedHerderTest { @Test public void testExternalZombieFencingRequestForSingleTaskConnector() throws Exception { + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); ClusterConfigState configState = exactlyOnceSnapshot( expectNewSessionKey(), Collections.singletonMap(TASK1, TASK_CONFIG), @@ -2902,6 +2943,7 @@ public class DistributedHerderTest { @Test public void testExternalZombieFencingRequestForFreshConnector() throws Exception { + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); ClusterConfigState configState = exactlyOnceSnapshot( expectNewSessionKey(), TASK_CONFIGS_MAP, @@ -2954,6 +2996,7 @@ public class DistributedHerderTest { expectHerderStartup(); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); SessionKey sessionKey = expectNewSessionKey(); @@ -3013,6 +3056,7 @@ public class DistributedHerderTest { expectHerderStartup(); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); SessionKey sessionKey = expectNewSessionKey(); @@ -3056,6 +3100,7 @@ public class DistributedHerderTest { expectHerderStartup(); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); SessionKey sessionKey = expectNewSessionKey(); @@ -3125,6 +3170,7 @@ public class DistributedHerderTest { expectHerderStartup(); when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V2); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); SessionKey sessionKey = expectNewSessionKey(); @@ -3335,6 +3381,7 @@ public class DistributedHerderTest { final long maxPollWaitMs = rebalanceDelayMs - operationDelayMs; when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(connectProtocolVersion); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); // Assign the connector to this worker, and have it start expectRebalance(Collections.emptyList(), Collections.emptyList(), ConnectProtocol.Assignment.NO_ERROR, 1, singletonList(CONN1), Collections.emptyList(), rebalanceDelayMs); @@ -3396,6 +3443,7 @@ public class DistributedHerderTest { public void testTaskReconfigurationRetriesWithConnectorTaskConfigsException() { when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -3417,6 +3465,7 @@ public class DistributedHerderTest { // initial tick when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -3463,6 +3512,7 @@ public class DistributedHerderTest { when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(worker.isSinkConnector(CONN1)).thenReturn(Boolean.TRUE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), false); expectConfigRefreshAndSnapshot(SNAPSHOT); @@ -3615,8 +3665,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.EXACTLY_ONCE_SUPPORT_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains("The connector does not implement the API required for preflight validation of exactly-once source support.")); + errors.get(0).contains("The connector does not implement the API required for preflight validation of exactly-once source support."), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3636,8 +3686,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.EXACTLY_ONCE_SUPPORT_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains(errorMessage)); + errors.get(0).contains(errorMessage), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3672,8 +3722,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.EXACTLY_ONCE_SUPPORT_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains("String must be one of (case insensitive): ")); + errors.get(0).contains("String must be one of (case insensitive): "), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3710,8 +3760,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.TRANSACTION_BOUNDARY_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains("The connector does not support connector-defined transaction boundaries with the given configuration.")); + errors.get(0).contains("The connector does not support connector-defined transaction boundaries with the given configuration."), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3731,8 +3781,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.TRANSACTION_BOUNDARY_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains(errorMessage)); + errors.get(0).contains(errorMessage), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3750,8 +3800,8 @@ public class DistributedHerderTest { List errors = validatedConfigs.get(SourceConnectorConfig.TRANSACTION_BOUNDARY_CONFIG).errorMessages(); assertFalse(errors.isEmpty()); assertTrue( - "Error message did not contain expected text: " + errors.get(0), - errors.get(0).contains("String must be one of (case insensitive): ")); + errors.get(0).contains("String must be one of (case insensitive): "), + "Error message did not contain expected text: " + errors.get(0)); assertEquals(1, errors.size()); } @@ -3787,7 +3837,7 @@ public class DistributedHerderTest { } @Test - public void testModifyConnectorOffsetsUnknownConnector() throws Exception { + public void testModifyConnectorOffsetsUnknownConnector() { // Get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -3805,7 +3855,7 @@ public class DistributedHerderTest { } @Test - public void testModifyOffsetsConnectorNotInStoppedState() throws Exception { + public void testModifyOffsetsConnectorNotInStoppedState() { // Get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -3823,7 +3873,7 @@ public class DistributedHerderTest { } @Test - public void testModifyOffsetsNotLeader() throws Exception { + public void testModifyOffsetsNotLeader() { // Get the initial assignment when(member.memberId()).thenReturn("member"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); @@ -3875,6 +3925,7 @@ public class DistributedHerderTest { // Get the initial assignment when(member.memberId()).thenReturn("leader"); when(member.currentProtocolVersion()).thenReturn(CONNECT_PROTOCOL_V0); + when(herder.connectorType(anyMap())).thenReturn(ConnectorType.SOURCE); expectRebalance(1, Collections.emptyList(), Collections.emptyList(), true); expectConfigRefreshAndSnapshot(SNAPSHOT_STOPPED_CONN1); herder.tick(); @@ -3960,7 +4011,7 @@ public class DistributedHerderTest { } @Test - public void testModifyOffsetsSourceConnectorExactlyOnceEnabledZombieFencingFailure() throws Exception { + public void testModifyOffsetsSourceConnectorExactlyOnceEnabledZombieFencingFailure() { // Setup herder with exactly-once support for source connectors enabled herder = exactlyOnceHerder(); rebalanceListener = herder.new RebalanceListener(time); @@ -4209,7 +4260,7 @@ public class DistributedHerderTest { private void stopBackgroundHerder() throws Exception { herder.stop(); herderExecutor.shutdown(); - assertTrue("herder thread did not finish in time", herderExecutor.awaitTermination(10, TimeUnit.SECONDS)); + assertTrue(herderExecutor.awaitTermination(10, TimeUnit.SECONDS), "herder thread did not finish in time"); herderFuture.get(); assertTrue(noneConnectorClientConfigOverridePolicy.isClosed()); } @@ -4313,7 +4364,7 @@ public class DistributedHerderTest { } @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + public boolean awaitTermination(long timeout, TimeUnit unit) { return false; } } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/IncrementalCooperativeAssignorTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/IncrementalCooperativeAssignorTest.java index 48b7973fdc2..a2dc414f12a 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/IncrementalCooperativeAssignorTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/IncrementalCooperativeAssignorTest.java @@ -27,10 +27,12 @@ import org.apache.kafka.connect.storage.AppliedConnectorConfig; import org.apache.kafka.connect.util.ConnectUtils; import org.apache.kafka.connect.storage.ClusterConfigState; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -49,16 +51,17 @@ import java.util.stream.IntStream; import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeAssignor.ClusterAssignment; import static org.apache.kafka.connect.runtime.distributed.WorkerCoordinator.WorkerLoad; import static org.apache.kafka.connect.util.ConnectUtils.transformValues; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class IncrementalCooperativeAssignorTest { // Offset isn't used in most tests but is required for creating a config snapshot object, @@ -73,7 +76,7 @@ public class IncrementalCooperativeAssignorTest { private ClusterAssignment returnedAssignments; private Map memberAssignments; - @Before + @BeforeEach public void setup() { generationId = 1000; time = Time.SYSTEM; @@ -730,9 +733,9 @@ public class IncrementalCooperativeAssignorTest { new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); @@ -747,9 +750,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -762,9 +765,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.singleton(flakyWorker), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.singleton(flakyWorker), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -775,17 +778,17 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertTrue("Wrong assignment of lost connectors", - configuredAssignment.getOrDefault(flakyWorker, new WorkerLoad.Builder(flakyWorker).build()) - .connectors() - .containsAll(lostAssignments.connectors())); - assertTrue("Wrong assignment of lost tasks", - configuredAssignment.getOrDefault(flakyWorker, new WorkerLoad.Builder(flakyWorker).build()) - .tasks() - .containsAll(lostAssignments.tasks())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertTrue(configuredAssignment.getOrDefault(flakyWorker, new WorkerLoad.Builder(flakyWorker).build()) + .connectors() + .containsAll(lostAssignments.connectors()), + "Wrong assignment of lost connectors"); + assertTrue(configuredAssignment.getOrDefault(flakyWorker, new WorkerLoad.Builder(flakyWorker).build()) + .tasks() + .containsAll(lostAssignments.tasks()), + "Wrong assignment of lost tasks"); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); } @@ -810,9 +813,9 @@ public class IncrementalCooperativeAssignorTest { new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); @@ -827,9 +830,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -841,9 +844,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -853,13 +856,13 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, lostAssignmentsToReassign, new ArrayList<>(configuredAssignment.values())); - assertTrue("Wrong assignment of lost connectors", - lostAssignmentsToReassign.build().connectors().containsAll(lostAssignments.connectors())); - assertTrue("Wrong assignment of lost tasks", - lostAssignmentsToReassign.build().tasks().containsAll(lostAssignments.tasks())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertTrue(lostAssignmentsToReassign.build().connectors().containsAll(lostAssignments.connectors()), + "Wrong assignment of lost connectors"); + assertTrue(lostAssignmentsToReassign.build().tasks().containsAll(lostAssignments.tasks()), + "Wrong assignment of lost tasks"); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); } @@ -884,9 +887,9 @@ public class IncrementalCooperativeAssignorTest { new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); @@ -904,9 +907,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.singleton(newWorker), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.singleton(newWorker), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -921,9 +924,9 @@ public class IncrementalCooperativeAssignorTest { Set expectedWorkers = new HashSet<>(); expectedWorkers.addAll(Arrays.asList(newWorker, flakyWorker)); - assertEquals("Wrong set of workers for reassignments", - expectedWorkers, - assignor.candidateWorkersForReassignment); + assertEquals(expectedWorkers, + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -949,13 +952,13 @@ public class IncrementalCooperativeAssignorTest { .tasks()); listOfTasksInLast2Workers.addAll(configuredAssignment.getOrDefault(flakyWorker, new WorkerLoad.Builder(flakyWorker).build()) .tasks()); - assertTrue("Wrong assignment of lost connectors", - listOfConnectorsInLast2Workers.containsAll(lostAssignments.connectors())); - assertTrue("Wrong assignment of lost tasks", - listOfTasksInLast2Workers.containsAll(lostAssignments.tasks())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertTrue(listOfConnectorsInLast2Workers.containsAll(lostAssignments.connectors()), + "Wrong assignment of lost connectors"); + assertTrue(listOfTasksInLast2Workers.containsAll(lostAssignments.tasks()), + "Wrong assignment of lost tasks"); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); } @@ -980,9 +983,9 @@ public class IncrementalCooperativeAssignorTest { new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); @@ -997,9 +1000,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -1012,9 +1015,9 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.singleton(veryFlakyWorker), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.singleton(veryFlakyWorker), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(time.milliseconds() + rebalanceDelay, assignor.scheduledRebalance); assertEquals(rebalanceDelay, assignor.delay); @@ -1027,13 +1030,13 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, lostAssignmentsToReassign, new ArrayList<>(configuredAssignment.values())); - assertTrue("Wrong assignment of lost connectors", - lostAssignmentsToReassign.build().connectors().containsAll(lostAssignments.connectors())); - assertTrue("Wrong assignment of lost tasks", - lostAssignmentsToReassign.build().tasks().containsAll(lostAssignments.tasks())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertTrue(lostAssignmentsToReassign.build().connectors().containsAll(lostAssignments.connectors()), + "Wrong assignment of lost connectors"); + assertTrue(lostAssignmentsToReassign.build().tasks().containsAll(lostAssignments.tasks()), + "Wrong assignment of lost tasks"); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); } @@ -1059,9 +1062,9 @@ public class IncrementalCooperativeAssignorTest { new ConnectorsAndTasks.Builder(), new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); @@ -1077,15 +1080,15 @@ public class IncrementalCooperativeAssignorTest { assignor.handleLostAssignments(lostAssignments, lostAssignmentsToReassign, new ArrayList<>(configuredAssignment.values())); - assertEquals("Wrong set of workers for reassignments", - Collections.emptySet(), - assignor.candidateWorkersForReassignment); + assertEquals(Collections.emptySet(), + assignor.candidateWorkersForReassignment, + "Wrong set of workers for reassignments"); assertEquals(0, assignor.scheduledRebalance); assertEquals(0, assignor.delay); - assertEquals("Wrong assignment of lost connectors", - lostAssignments.connectors(), lostAssignmentsToReassign.build().connectors()); - assertEquals("Wrong assignment of lost tasks", - lostAssignments.tasks(), lostAssignmentsToReassign.build().tasks()); + assertEquals(lostAssignments.connectors(), + lostAssignmentsToReassign.build().connectors(), "Wrong assignment of lost connectors"); + assertEquals(lostAssignments.tasks(), + lostAssignmentsToReassign.build().tasks(), "Wrong assignment of lost tasks"); } @Test @@ -1240,9 +1243,9 @@ public class IncrementalCooperativeAssignorTest { serializedAssignments.forEach((worker, serializedAssignment) -> { ExtendedAssignment assignment = IncrementalCooperativeConnectProtocol.deserializeAssignment(serializedAssignment); assertEquals( - "Incorrect protocol version in assignment for worker " + worker, IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V1, - assignment.version() + assignment.version(), + "Incorrect protocol version in assignment for worker " + worker ); }); } @@ -1281,9 +1284,9 @@ public class IncrementalCooperativeAssignorTest { serializedAssignments.forEach((worker, serializedAssignment) -> { ExtendedAssignment assignment = IncrementalCooperativeConnectProtocol.deserializeAssignment(serializedAssignment); assertEquals( - "Incorrect protocol version in assignment for worker " + worker, IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V2, - assignment.version() + assignment.version(), + "Incorrect protocol version in assignment for worker " + worker ); }); } @@ -1332,16 +1335,16 @@ public class IncrementalCooperativeAssignorTest { private void addNewWorker(String worker, List connectors, List tasks) { ConnectorsAndTasks assignment = new ConnectorsAndTasks.Builder().with(connectors, tasks).build(); assertNull( - "Worker " + worker + " already exists", - memberAssignments.put(worker, assignment) + memberAssignments.put(worker, assignment), + "Worker " + worker + " already exists" ); } private void removeWorkers(String... workers) { for (String worker : workers) { assertNotNull( - "Worker " + worker + " does not exist", - memberAssignments.remove(worker) + memberAssignments.remove(worker), + "Worker " + worker + " does not exist" ); } } @@ -1375,15 +1378,15 @@ public class IncrementalCooperativeAssignorTest { private void addNewConnector(String connector, int taskCount) { assertNull( - "Connector " + connector + " already exists", - connectors.put(connector, taskCount) + connectors.put(connector, taskCount), + "Connector " + connector + " already exists" ); } private void removeConnector(String connector) { assertNotNull( - "Connector " + connector + " does not exist", - connectors.remove(connector) + connectors.remove(connector), + "Connector " + connector + " does not exist" ); } @@ -1425,50 +1428,34 @@ public class IncrementalCooperativeAssignorTest { workerAssignment.tasks().removeAll(returnedAssignments.newlyRevokedTasks(worker)); workerAssignment.tasks().addAll(returnedAssignments.newlyAssignedTasks(worker)); - assertEquals( - "Complete connector assignment for worker " + worker + " does not match expectations " + - "based on prior assignment and new revocations and assignments", - new HashSet<>(workerAssignment.connectors()), - new HashSet<>(returnedAssignments.allAssignedConnectors().get(worker)) - ); - assertEquals( - "Complete task assignment for worker " + worker + " does not match expectations " + - "based on prior assignment and new revocations and assignments", - new HashSet<>(workerAssignment.tasks()), - new HashSet<>(returnedAssignments.allAssignedTasks().get(worker)) - ); + assertEquals(new HashSet<>(workerAssignment.connectors()), + new HashSet<>(returnedAssignments.allAssignedConnectors().get(worker)), + "Complete connector assignment for worker " + worker + " does not match expectations " + + "based on prior assignment and new revocations and assignments"); + assertEquals(new HashSet<>(workerAssignment.tasks()), + new HashSet<>(returnedAssignments.allAssignedTasks().get(worker)), + "Complete task assignment for worker " + worker + " does not match expectations " + + "based on prior assignment and new revocations and assignments"); }); } private void assertEmptyAssignment() { - assertEquals( - "No connectors should have been newly assigned during this round", - Collections.emptyList(), - ConnectUtils.combineCollections(returnedAssignments.newlyAssignedConnectors().values()) - ); - assertEquals( - "No tasks should have been newly assigned during this round", - Collections.emptyList(), - ConnectUtils.combineCollections(returnedAssignments.newlyAssignedTasks().values()) - ); - assertEquals( - "No connectors should have been revoked during this round", - Collections.emptyList(), - ConnectUtils.combineCollections(returnedAssignments.newlyRevokedConnectors().values()) - ); - assertEquals( - "No tasks should have been revoked during this round", - Collections.emptyList(), - ConnectUtils.combineCollections(returnedAssignments.newlyRevokedTasks().values()) - ); + assertEquals(Collections.emptyList(), + ConnectUtils.combineCollections(returnedAssignments.newlyAssignedConnectors().values()), + "No connectors should have been newly assigned during this round"); + assertEquals(Collections.emptyList(), + ConnectUtils.combineCollections(returnedAssignments.newlyAssignedTasks().values()), + "No tasks should have been newly assigned during this round"); + assertEquals(Collections.emptyList(), + ConnectUtils.combineCollections(returnedAssignments.newlyRevokedConnectors().values()), + "No connectors should have been revoked during this round"); + assertEquals(Collections.emptyList(), + ConnectUtils.combineCollections(returnedAssignments.newlyRevokedTasks().values()), + "No tasks should have been revoked during this round"); } private void assertWorkers(String... workers) { - assertEquals( - "Wrong set of workers", - new HashSet<>(Arrays.asList(workers)), - returnedAssignments.allWorkers() - ); + assertEquals(new HashSet<>(Arrays.asList(workers)), returnedAssignments.allWorkers(), "Wrong set of workers"); } /** @@ -1497,11 +1484,9 @@ public class IncrementalCooperativeAssignorTest { .sorted() .collect(Collectors.toList()); List actualAllocations = allocations(allocation); - assertEquals( - "Allocation of assigned " + allocated + " across cluster does not match expected counts", - expectedAllocations, - actualAllocations - ); + assertEquals(expectedAllocations, + actualAllocations, + "Allocation of assigned " + allocated + " across cluster does not match expected counts"); } private List allocations(Function> allocation) { @@ -1515,25 +1500,25 @@ public class IncrementalCooperativeAssignorTest { private void assertNoRevocations() { returnedAssignments.newlyRevokedConnectors().forEach((worker, revocations) -> assertEquals( - "Expected no revocations to take place during this round, but connector revocations were issued for worker " + worker, - Collections.emptySet(), - new HashSet<>(revocations) - ) + Collections.emptySet(), + new HashSet<>(revocations), + "Expected no revocations to take place during this round, but connector revocations were issued for worker " + worker + ) ); returnedAssignments.newlyRevokedTasks().forEach((worker, revocations) -> assertEquals( - "Expected no revocations to take place during this round, but task revocations were issued for worker " + worker, - Collections.emptySet(), - new HashSet<>(revocations) - ) + Collections.emptySet(), + new HashSet<>(revocations), + "Expected no revocations to take place during this round, but task revocations were issued for worker " + worker + ) ); } private void assertDelay(int expectedDelay) { assertEquals( - "Wrong rebalance delay", expectedDelay, - assignor.delay + assignor.delay, + "Wrong rebalance delay" ); } @@ -1557,13 +1542,13 @@ public class IncrementalCooperativeAssignorTest { ); existingConnectors.retainAll(newConnectors); - assertEquals("Found connectors in new assignment that already exist in current assignment", - Collections.emptyList(), - existingConnectors); + assertEquals(Collections.emptyList(), + existingConnectors, + "Found connectors in new assignment that already exist in current assignment"); existingTasks.retainAll(newTasks); - assertEquals("Found tasks in new assignment that already exist in current assignment", - Collections.emptyList(), - existingConnectors); + assertEquals(Collections.emptyList(), + existingConnectors, + "Found tasks in new assignment that already exist in current assignment"); } private void assertBalancedAndCompleteAllocation() { @@ -1581,23 +1566,17 @@ public class IncrementalCooperativeAssignorTest { int minTasks = taskCounts.get(0); int maxTasks = taskCounts.get(taskCounts.size() - 1); - assertTrue( - "Assignments are imbalanced. The spread of connectors across each worker is: " + connectorCounts, - maxConnectors - minConnectors <= 1 - ); - assertTrue( - "Assignments are imbalanced. The spread of tasks across each worker is: " + taskCounts, - maxTasks - minTasks <= 1 - ); + assertTrue(maxConnectors - minConnectors <= 1, + "Assignments are imbalanced. The spread of connectors across each worker is: " + connectorCounts); + assertTrue(maxTasks - minTasks <= 1, + "Assignments are imbalanced. The spread of tasks across each worker is: " + taskCounts); } private void assertCompleteAllocation() { List allAssignedConnectors = ConnectUtils.combineCollections(memberAssignments.values(), ConnectorsAndTasks::connectors); - assertEquals( - "The set of connectors assigned across the cluster does not match the set of connectors in the config topic", - connectors.keySet(), - new HashSet<>(allAssignedConnectors) - ); + assertEquals(connectors.keySet(), + new HashSet<>(allAssignedConnectors), + "The set of connectors assigned across the cluster does not match the set of connectors in the config topic"); Map> allAssignedTasks = ConnectUtils.combineCollections(memberAssignments.values(), ConnectorsAndTasks::tasks) .stream() @@ -1607,20 +1586,14 @@ public class IncrementalCooperativeAssignorTest { Set expectedTasks = IntStream.range(0, taskCount) .mapToObj(i -> new ConnectorTaskId(connector, i)) .collect(Collectors.toSet()); - assertEquals( - "The set of tasks assigned across the cluster for connector " + connector + " does not match the set of tasks in the config topic", - expectedTasks, - new HashSet<>(allAssignedTasks.get(connector)) - ); + assertEquals(expectedTasks, + new HashSet<>(allAssignedTasks.get(connector)), + "The set of tasks assigned across the cluster for connector " + connector + " does not match the set of tasks in the config topic"); }); } private static void assertNoDuplicates(List collection, String assertionMessage) { - assertEquals( - assertionMessage, - new HashSet<>(collection).size(), - collection.size() - ); + assertEquals(new HashSet<>(collection).size(), collection.size(), assertionMessage); } } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorIncrementalTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorIncrementalTest.java index ca5c3bdc6f8..c15be119619 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorIncrementalTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorIncrementalTest.java @@ -29,15 +29,14 @@ import org.apache.kafka.common.utils.MockTime; import org.apache.kafka.connect.storage.ClusterConfigState; import org.apache.kafka.connect.storage.KafkaConfigBackingStore; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import java.nio.ByteBuffer; @@ -49,6 +48,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Stream; import static org.apache.kafka.common.message.JoinGroupRequestData.JoinGroupRequestProtocol; import static org.apache.kafka.common.message.JoinGroupRequestData.JoinGroupRequestProtocolCollection; @@ -58,22 +58,18 @@ import static org.apache.kafka.connect.runtime.WorkerTestUtils.clusterConfigStat import static org.apache.kafka.connect.runtime.distributed.ConnectProtocol.WorkerState; import static org.apache.kafka.connect.runtime.distributed.ConnectProtocolCompatibility.COMPATIBLE; import static org.apache.kafka.connect.runtime.distributed.ConnectProtocolCompatibility.EAGER; -import static org.apache.kafka.connect.runtime.distributed.ConnectProtocolCompatibility.SESSIONED; import static org.apache.kafka.connect.runtime.distributed.IncrementalCooperativeConnectProtocol.CONNECT_PROTOCOL_V1; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.runners.Parameterized.Parameter; -import static org.junit.runners.Parameterized.Parameters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -@RunWith(value = Parameterized.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class WorkerCoordinatorIncrementalTest { - @Rule - public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); private final String connectorId1 = "connector1"; private final String connectorId2 = "connector2"; @@ -116,19 +112,14 @@ public class WorkerCoordinatorIncrementalTest { // Arguments are: // - Protocol type // - Expected metadata size - @Parameters - public static Iterable mode() { - return Arrays.asList(new Object[][]{{COMPATIBLE, 2}, {SESSIONED, 3}}); + static Stream mode() { + return Stream.of( + Arguments.of(ConnectProtocolCompatibility.COMPATIBLE, 2), + Arguments.of(ConnectProtocolCompatibility.SESSIONED, 3) + ); } - @Parameter - public ConnectProtocolCompatibility compatibility; - - @Parameter(1) - public int expectedMetadataSize; - - @Before - public void setup() { + public void init(ConnectProtocolCompatibility compatibility) { LogContext loggerFactory = new LogContext(); this.time = new MockTime(); @@ -137,7 +128,7 @@ public class WorkerCoordinatorIncrementalTest { this.client.updateMetadata(RequestTestUtils.metadataUpdateWith(1, Collections.singletonMap("topic", 1))); this.node = metadata.fetch().nodes().get(0); this.consumerClient = new ConsumerNetworkClient(loggerFactory, client, metadata, time, - retryBackoffMs, requestTimeoutMs, heartbeatIntervalMs); + retryBackoffMs, requestTimeoutMs, heartbeatIntervalMs); this.metrics = new Metrics(time); this.rebalanceListener = new MockRebalanceListener(); @@ -153,29 +144,29 @@ public class WorkerCoordinatorIncrementalTest { this.configStorageCalls = 0; this.rebalanceConfig = new GroupRebalanceConfig(sessionTimeoutMs, - rebalanceTimeoutMs, - heartbeatIntervalMs, - groupId, - Optional.empty(), - retryBackoffMs, - retryBackoffMaxMs, - true); + rebalanceTimeoutMs, + heartbeatIntervalMs, + groupId, + Optional.empty(), + retryBackoffMs, + retryBackoffMaxMs, + true); this.coordinator = new WorkerCoordinator(rebalanceConfig, - loggerFactory, - consumerClient, - metrics, - "worker" + groupId, - time, - expectedUrl(leaderId), - configStorage, - rebalanceListener, - compatibility, - rebalanceDelay); + loggerFactory, + consumerClient, + metrics, + "worker" + groupId, + time, + expectedUrl(leaderId), + configStorage, + rebalanceListener, + compatibility, + rebalanceDelay); configState1 = clusterConfigState(offset, 2, 4); } - @After + @AfterEach public void teardown() { this.metrics.close(); verifyNoMoreInteractions(configStorage); @@ -188,8 +179,11 @@ public class WorkerCoordinatorIncrementalTest { // We only test functionality unique to WorkerCoordinator. Other functionality is already // well tested via the tests that cover AbstractCoordinator & ConsumerCoordinator. - @Test - public void testMetadata() { + @ParameterizedTest + @MethodSource("mode") + public void testMetadata(ConnectProtocolCompatibility compatibility, int expectedMetadataSize) { + init(compatibility); + System.err.println(compatibility); when(configStorage.snapshot()).thenReturn(configState1); JoinGroupRequestProtocolCollection serialized = coordinator.metadata(); @@ -206,8 +200,10 @@ public class WorkerCoordinatorIncrementalTest { verify(configStorage, times(1)).snapshot(); } - @Test - public void testMetadataWithExistingAssignment() { + @ParameterizedTest + @MethodSource("mode") + public void testMetadataWithExistingAssignment(ConnectProtocolCompatibility compatibility, int expectedMetadataSize) { + init(compatibility); when(configStorage.snapshot()).thenReturn(configState1); ExtendedAssignment assignment = new ExtendedAssignment( @@ -237,8 +233,10 @@ public class WorkerCoordinatorIncrementalTest { verify(configStorage, times(1)).snapshot(); } - @Test - public void testMetadataWithExistingAssignmentButOlderProtocolSelection() { + @ParameterizedTest + @MethodSource("mode") + public void testMetadataWithExistingAssignmentButOlderProtocolSelection(ConnectProtocolCompatibility compatibility, int expectedMetadataSize) { + init(compatibility); when(configStorage.snapshot()).thenReturn(configState1); ExtendedAssignment assignment = new ExtendedAssignment( @@ -266,16 +264,18 @@ public class WorkerCoordinatorIncrementalTest { verify(configStorage, times(1)).snapshot(); } - @Test - public void testTaskAssignmentWhenWorkerJoins() { + @ParameterizedTest + @MethodSource("mode") + public void testTaskAssignmentWhenWorkerJoins(ConnectProtocolCompatibility compatibility) { + init(compatibility); when(configStorage.snapshot()).thenReturn(configState1); coordinator.metadata(); ++configStorageCalls; List responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, null); - addJoinGroupResponseMember(responseMembers, memberId, offset, null); + addJoinGroupResponseMember(responseMembers, leaderId, offset, null, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, null, compatibility); Map result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -295,9 +295,9 @@ public class WorkerCoordinatorIncrementalTest { ++configStorageCalls; responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment); - addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment); - addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null); + addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment, compatibility); + addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null, compatibility); result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -323,8 +323,10 @@ public class WorkerCoordinatorIncrementalTest { verify(configStorage, times(configStorageCalls)).snapshot(); } - @Test - public void testTaskAssignmentWhenWorkerLeavesPermanently() { + @ParameterizedTest + @MethodSource("mode") + public void testTaskAssignmentWhenWorkerLeavesPermanently(ConnectProtocolCompatibility compatibility) { + init(compatibility); when(configStorage.snapshot()).thenReturn(configState1); // First assignment distributes configured connectors and tasks @@ -332,9 +334,9 @@ public class WorkerCoordinatorIncrementalTest { ++configStorageCalls; List responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, null); - addJoinGroupResponseMember(responseMembers, memberId, offset, null); - addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null); + addJoinGroupResponseMember(responseMembers, leaderId, offset, null, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, null, compatibility); + addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null, compatibility); Map result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -362,8 +364,8 @@ public class WorkerCoordinatorIncrementalTest { // Mark everyone as in sync with configState1 responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment); - addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment); + addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment, compatibility); result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -421,8 +423,10 @@ public class WorkerCoordinatorIncrementalTest { verify(configStorage, times(configStorageCalls)).snapshot(); } - @Test - public void testTaskAssignmentWhenWorkerBounces() { + @ParameterizedTest + @MethodSource("mode") + public void testTaskAssignmentWhenWorkerBounces(ConnectProtocolCompatibility compatibility) { + init(compatibility); when(configStorage.snapshot()).thenReturn(configState1); // First assignment distributes configured connectors and tasks @@ -430,9 +434,9 @@ public class WorkerCoordinatorIncrementalTest { ++configStorageCalls; List responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, null); - addJoinGroupResponseMember(responseMembers, memberId, offset, null); - addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null); + addJoinGroupResponseMember(responseMembers, leaderId, offset, null, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, null, compatibility); + addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null, compatibility); Map result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -459,8 +463,8 @@ public class WorkerCoordinatorIncrementalTest { ++configStorageCalls; responseMembers = new ArrayList<>(); - addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment); - addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment); + addJoinGroupResponseMember(responseMembers, leaderId, offset, leaderAssignment, compatibility); + addJoinGroupResponseMember(responseMembers, memberId, offset, memberAssignment, compatibility); result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); @@ -483,7 +487,7 @@ public class WorkerCoordinatorIncrementalTest { // A third rebalance before the delay expires won't change the assignments even if the // member returns in the meantime - addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null); + addJoinGroupResponseMember(responseMembers, anotherMemberId, offset, null, compatibility); result = coordinator.onLeaderElected(leaderId, compatibility.protocol(), responseMembers, false); leaderAssignment = deserializeAssignment(result, leaderId); @@ -569,10 +573,12 @@ public class WorkerCoordinatorIncrementalTest { return IncrementalCooperativeConnectProtocol.deserializeAssignment(assignment.get(member)); } + private void addJoinGroupResponseMember(List responseMembers, - String member, - long offset, - ExtendedAssignment assignment) { + String member, + long offset, + ExtendedAssignment assignment, + ConnectProtocolCompatibility compatibility) { responseMembers.add(new JoinGroupResponseMember() .setMemberId(member) .setMetadata( diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorTest.java index 1911eb10b13..fd8c5790720 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerCoordinatorTest.java @@ -41,15 +41,14 @@ import org.apache.kafka.connect.storage.AppliedConnectorConfig; import org.apache.kafka.connect.storage.ClusterConfigState; import org.apache.kafka.connect.storage.KafkaConfigBackingStore; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import java.nio.ByteBuffer; @@ -63,26 +62,23 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.apache.kafka.connect.runtime.distributed.ConnectProtocolCompatibility.COMPATIBLE; import static org.apache.kafka.connect.runtime.distributed.ConnectProtocolCompatibility.EAGER; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertThrows; -import static org.junit.runners.Parameterized.Parameter; -import static org.junit.runners.Parameterized.Parameters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(value = Parameterized.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class WorkerCoordinatorTest { - @Rule - public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - private static final String LEADER_URL = "leaderUrl:8083"; private static final String MEMBER_URL = "memberUrl:8083"; @@ -118,21 +114,14 @@ public class WorkerCoordinatorTest { // Arguments are: // - Protocol type // - Expected metadata size - @Parameters - public static Iterable mode() { - return Arrays.asList(new Object[][]{ - {EAGER, 1}, - {COMPATIBLE, 2}}); + static Stream mode() { + return Stream.of( + Arguments.of(EAGER, 1), + Arguments.of(COMPATIBLE, 2) + ); } - @Parameter - public ConnectProtocolCompatibility compatibility; - - @Parameter(1) - public int expectedMetadataSize; - - @Before - public void setup() { + public void setup(ConnectProtocolCompatibility compatibility) { LogContext logContext = new LogContext(); this.time = new MockTime(); @@ -241,7 +230,7 @@ public class WorkerCoordinatorTest { ); } - @After + @AfterEach public void teardown() { this.metrics.close(); } @@ -249,8 +238,10 @@ public class WorkerCoordinatorTest { // We only test functionality unique to WorkerCoordinator. Most functionality is already well tested via the tests // that cover AbstractCoordinator & ConsumerCoordinator. - @Test - public void testMetadata() { + @ParameterizedTest + @MethodSource("mode") + public void testMetadata(ConnectProtocolCompatibility compatibility, int expectedMetadataSize) { + setup(compatibility); when(configStorage.snapshot()).thenReturn(configState1); JoinGroupRequestData.JoinGroupRequestProtocolCollection serialized = coordinator.metadata(); @@ -267,8 +258,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testNormalJoinGroupLeader() { + @ParameterizedTest + @MethodSource("mode") + public void testNormalJoinGroupLeader(ConnectProtocolCompatibility compatibility) { + setup(compatibility); when(configStorage.snapshot()).thenReturn(configState1); final String memberId = "leader"; @@ -302,8 +295,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testNormalJoinGroupFollower() { + @ParameterizedTest + @MethodSource("mode") + public void testNormalJoinGroupFollower(ConnectProtocolCompatibility compatibility) { + setup(compatibility); when(configStorage.snapshot()).thenReturn(configState1); final String memberId = "member"; @@ -333,8 +328,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testJoinLeaderCannotAssign() { + @ParameterizedTest + @MethodSource("mode") + public void testJoinLeaderCannotAssign(ConnectProtocolCompatibility compatibility) { + setup(compatibility); // If the selected leader can't get up to the maximum offset, it will fail to assign and we should immediately // need to retry the join. when(configStorage.snapshot()).thenReturn(configState1); @@ -366,8 +363,10 @@ public class WorkerCoordinatorTest { verify(configStorage, times(2)).snapshot(); } - @Test - public void testRejoinGroup() { + @ParameterizedTest + @MethodSource("mode") + public void testRejoinGroup(ConnectProtocolCompatibility compatibility) { + setup(compatibility); when(configStorage.snapshot()).thenReturn(configState1); client.prepareResponse(FindCoordinatorResponse.prepareResponse(Errors.NONE, groupId, node)); @@ -405,8 +404,10 @@ public class WorkerCoordinatorTest { verify(configStorage, times(2)).snapshot(); } - @Test - public void testLeaderPerformAssignment1() { + @ParameterizedTest + @MethodSource("mode") + public void testLeaderPerformAssignment1(ConnectProtocolCompatibility compatibility) { + setup(compatibility); // Since all the protocol responses are mocked, the other tests validate doSync runs, but don't validate its // output. So we test it directly here. @@ -445,8 +446,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testLeaderPerformAssignment2() { + @ParameterizedTest + @MethodSource("mode") + public void testLeaderPerformAssignment2(ConnectProtocolCompatibility compatibility) { + setup(compatibility); // Since all the protocol responses are mocked, the other tests validate doSync runs, but don't validate its // output. So we test it directly here. @@ -486,8 +489,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testLeaderPerformAssignmentSingleTaskConnectors() { + @ParameterizedTest + @MethodSource("mode") + public void testLeaderPerformAssignmentSingleTaskConnectors(ConnectProtocolCompatibility compatibility) { + setup(compatibility); // Since all the protocol responses are mocked, the other tests validate doSync runs, but don't validate its // output. So we test it directly here. @@ -528,8 +533,10 @@ public class WorkerCoordinatorTest { verify(configStorage).snapshot(); } - @Test - public void testSkippingAssignmentFails() { + @ParameterizedTest + @MethodSource("mode") + public void testSkippingAssignmentFails(ConnectProtocolCompatibility compatibility) { + setup(compatibility); // Connect does not support static membership so skipping assignment should // never be set to true by the group coordinator. It is treated as an // illegal state if it would. diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerGroupMemberTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerGroupMemberTest.java index 77d70d8fd9a..8d6db432502 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerGroupMemberTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/distributed/WorkerGroupMemberTest.java @@ -26,10 +26,12 @@ import org.apache.kafka.common.utils.Time; import org.apache.kafka.connect.runtime.MockConnectMetrics; import org.apache.kafka.connect.runtime.WorkerConfig; import org.apache.kafka.connect.storage.ConfigBackingStore; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -37,15 +39,16 @@ import java.lang.management.ManagementFactory; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class WorkerGroupMemberTest { @Mock private ConfigBackingStore configBackingStore; @@ -83,8 +86,8 @@ public class WorkerGroupMemberTest { foundJmxReporter = true; } } - assertTrue("Failed to find MockMetricsReporter", foundMockReporter); - assertTrue("Failed to find JmxReporter", foundJmxReporter); + assertTrue(foundMockReporter, "Failed to find MockMetricsReporter"); + assertTrue(foundJmxReporter, "Failed to find JmxReporter"); MetricName name = member.metrics().metricName("test.avg", "grp1"); member.metrics().addMetric(name, new Avg()); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/ErrorReporterTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/ErrorReporterTest.java index e0018a13e95..bbc1bf99092 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/ErrorReporterTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/ErrorReporterTest.java @@ -31,12 +31,14 @@ import org.apache.kafka.connect.runtime.isolation.Plugins; import org.apache.kafka.connect.sink.SinkTask; import org.apache.kafka.connect.transforms.Transformation; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.util.HashMap; import java.util.Map; @@ -55,11 +57,11 @@ import static org.apache.kafka.connect.runtime.errors.DeadLetterQueueReporter.ER import static org.apache.kafka.connect.runtime.errors.DeadLetterQueueReporter.ERROR_HEADER_ORIG_TOPIC; import static org.apache.kafka.connect.runtime.errors.DeadLetterQueueReporter.ERROR_HEADER_STAGE; import static org.apache.kafka.connect.runtime.errors.DeadLetterQueueReporter.ERROR_HEADER_TASK_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +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.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; @@ -67,7 +69,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class ErrorReporterTest { private static final String TOPIC = "test-topic"; @@ -86,13 +89,13 @@ public class ErrorReporterTest { private ErrorHandlingMetrics errorHandlingMetrics; private MockConnectMetrics metrics; - @Before + @BeforeEach public void setup() { metrics = new MockConnectMetrics(); errorHandlingMetrics = new ErrorHandlingMetrics(new ConnectorTaskId("connector-", 1), metrics); } - @After + @AfterEach public void tearDown() { if (metrics != null) { metrics.stop(); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/RetryWithToleranceOperatorTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/RetryWithToleranceOperatorTest.java index 66d2e335599..e884e79e75d 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/RetryWithToleranceOperatorTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/RetryWithToleranceOperatorTest.java @@ -35,10 +35,12 @@ import org.apache.kafka.connect.sink.SinkConnector; import org.apache.kafka.connect.sink.SinkTask; import org.apache.kafka.connect.source.SourceRecord; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.mockito.stubbing.OngoingStubbing; import java.util.Arrays; @@ -65,11 +67,11 @@ import static org.apache.kafka.connect.runtime.ConnectorConfig.ERRORS_TOLERANCE_ import static org.apache.kafka.connect.runtime.ConnectorConfig.ERRORS_TOLERANCE_DEFAULT; import static org.apache.kafka.connect.runtime.errors.ToleranceType.ALL; import static org.apache.kafka.connect.runtime.errors.ToleranceType.NONE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +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.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doThrow; @@ -80,7 +82,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class RetryWithToleranceOperatorTest { private static final Map PROPERTIES = new HashMap() {{ @@ -358,15 +361,15 @@ public class RetryWithToleranceOperatorTest { public void testToleranceLimit() { RetryWithToleranceOperator> retryWithToleranceOperator = genericOperator(ERRORS_RETRY_TIMEOUT_DEFAULT, NONE, errorHandlingMetrics); retryWithToleranceOperator.markAsFailed(); - assertFalse("should not tolerate any errors", retryWithToleranceOperator.withinToleranceLimits()); + assertFalse(retryWithToleranceOperator.withinToleranceLimits(), "should not tolerate any errors"); retryWithToleranceOperator = genericOperator(ERRORS_RETRY_TIMEOUT_DEFAULT, ALL, errorHandlingMetrics); retryWithToleranceOperator.markAsFailed(); retryWithToleranceOperator.markAsFailed(); - assertTrue("should tolerate all errors", retryWithToleranceOperator.withinToleranceLimits()); + assertTrue(retryWithToleranceOperator.withinToleranceLimits(), "should tolerate all errors"); retryWithToleranceOperator = genericOperator(ERRORS_RETRY_TIMEOUT_DEFAULT, NONE, errorHandlingMetrics); - assertTrue("no tolerance is within limits if no failures", retryWithToleranceOperator.withinToleranceLimits()); + assertTrue(retryWithToleranceOperator.withinToleranceLimits(), "no tolerance is within limits if no failures"); } @Test diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/WorkerErrantRecordReporterTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/WorkerErrantRecordReporterTest.java index e84c832f644..847a229fae7 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/WorkerErrantRecordReporterTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/errors/WorkerErrantRecordReporterTest.java @@ -25,24 +25,27 @@ import org.apache.kafka.connect.runtime.ConnectorConfig; import org.apache.kafka.connect.runtime.InternalSinkRecord; import org.apache.kafka.connect.storage.Converter; import org.apache.kafka.connect.storage.HeaderConverter; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.concurrent.CompletableFuture; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class WorkerErrantRecordReporterTest { private WorkerErrantRecordReporter reporter; diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/health/ConnectClusterStateImplTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/health/ConnectClusterStateImplTest.java index 16c7f428311..eac2fc76532 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/health/ConnectClusterStateImplTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/health/ConnectClusterStateImplTest.java @@ -19,12 +19,14 @@ package org.apache.kafka.connect.runtime.health; import org.apache.kafka.connect.errors.ConnectException; import org.apache.kafka.connect.runtime.Herder; import org.apache.kafka.connect.util.Callback; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.util.Arrays; import java.util.Collection; @@ -33,13 +35,14 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class ConnectClusterStateImplTest { protected static final String KAFKA_CLUSTER_ID = "franzwashere"; @@ -49,7 +52,7 @@ public class ConnectClusterStateImplTest { protected long herderRequestTimeoutMs = TimeUnit.SECONDS.toMillis(10); protected Collection expectedConnectors; - @Before + @BeforeEach public void setUp() { expectedConnectors = Arrays.asList("sink1", "source1", "source2"); connectClusterState = new ConnectClusterStateImpl( @@ -86,11 +89,9 @@ public class ConnectClusterStateImplTest { Map actualConfig = connectClusterState.connectorConfig(connName); assertEquals(expectedConfig, actualConfig); - assertNotSame( - "Config should be copied in order to avoid mutation by REST extensions", - expectedConfig, - actualConfig - ); + assertNotSame(expectedConfig, + actualConfig, + "Config should be copied in order to avoid mutation by REST extensions"); } @Test diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/DelegatingClassLoaderTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/DelegatingClassLoaderTest.java index 70303e552af..5aa0aec6172 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/DelegatingClassLoaderTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/DelegatingClassLoaderTest.java @@ -17,10 +17,12 @@ package org.apache.kafka.connect.runtime.isolation; import org.apache.kafka.connect.sink.SinkConnector; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.net.MalformedURLException; import java.net.URL; @@ -28,12 +30,13 @@ import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class DelegatingClassLoaderTest { public PluginClassLoader parent; @@ -55,7 +58,7 @@ public class DelegatingClassLoaderTest { } } - @Before + @BeforeEach @SuppressWarnings({"unchecked"}) public void setUp() { parent = mock(PluginClassLoader.class); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginDescTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginDescTest.java index 12eac8c94de..75d4948d1d5 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginDescTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginDescTest.java @@ -26,16 +26,16 @@ import org.apache.kafka.connect.storage.Converter; import org.apache.kafka.connect.storage.HeaderConverter; import org.apache.kafka.connect.transforms.Transformation; import org.apache.kafka.connect.transforms.predicates.Predicate; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; import java.net.URL; import java.nio.file.Paths; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -48,7 +48,7 @@ public class PluginDescTest { private PluginClassLoader pluginLoader; private PluginClassLoader otherPluginLoader; - @Before + @BeforeEach public void setUp() throws Exception { // Fairly simple use case, thus no need to create a random directory here yet. URL location = Paths.get("/tmp").toUri().toURL(); @@ -285,8 +285,8 @@ public class PluginDescTest { otherPluginLoader ); - assertTrue("Different plugin loaders should have an ordering", - configProviderDescPluginPath.compareTo(configProviderDescOtherPluginLoader) != 0); + assertTrue(configProviderDescPluginPath.compareTo(configProviderDescOtherPluginLoader) != 0, + "Different plugin loaders should have an ordering"); PluginDesc jsonConverterPlugin = new PluginDesc<>( @@ -339,6 +339,6 @@ public class PluginDescTest { } private static void assertNewer(PluginDesc older, PluginDesc newer) { - assertTrue(newer + " should be newer than " + older, older.compareTo(newer) < 0); + assertTrue(older.compareTo(newer) < 0, newer + " should be newer than " + older); } } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginScannerTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginScannerTest.java index 4f20ccdeaae..70c9f79c85b 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginScannerTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginScannerTest.java @@ -17,161 +17,141 @@ package org.apache.kafka.connect.runtime.isolation; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -@RunWith(Parameterized.class) public class PluginScannerTest { private enum ScannerType { Reflection, ServiceLoader } - @Rule - public TemporaryFolder pluginDir = new TemporaryFolder(); + @TempDir + File pluginDir; - private final PluginScanner scanner; + private Map scannerMap; - @Parameterized.Parameters - public static Collection parameters() { - List values = new ArrayList<>(); - for (ScannerType type : ScannerType.values()) { - values.add(new Object[]{type}); - } - return values; + static Stream parameters() { + return Stream.of(new ReflectionScanner(), new ServiceLoaderScanner()); } - public PluginScannerTest(ScannerType scannerType) { - switch (scannerType) { - case Reflection: - this.scanner = new ReflectionScanner(); - break; - case ServiceLoader: - this.scanner = new ServiceLoaderScanner(); - break; - default: - throw new IllegalArgumentException("Unknown type " + scannerType); - } - } - - @BeforeClass + @BeforeAll public static void setUp() { // Work around a circular-dependency in TestPlugins. TestPlugins.pluginPath(); } - @Test - public void testScanningEmptyPluginPath() { - PluginScanResult result = scan( - Collections.emptySet() - ); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningEmptyPluginPath(PluginScanner scanner) { + PluginScanResult result = scan(scanner, Collections.emptySet()); assertTrue(result.isEmpty()); } - @Test - public void testScanningPluginClasses() { - PluginScanResult result = scan( - TestPlugins.pluginPath() - ); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningPluginClasses(PluginScanner scanner) { + PluginScanResult result = scan(scanner, TestPlugins.pluginPath()); Set classes = new HashSet<>(); result.forEach(pluginDesc -> classes.add(pluginDesc.className())); Set expectedClasses = new HashSet<>(TestPlugins.pluginClasses()); assertEquals(expectedClasses, classes); } - @Test - public void testScanningInvalidUberJar() throws Exception { - pluginDir.newFile("invalid.jar"); - - PluginScanResult result = scan( - Collections.singleton(pluginDir.getRoot().toPath().toAbsolutePath()) - ); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningInvalidUberJar(PluginScanner scanner) throws Exception { + File newFile = new File(pluginDir, "invalid.jar"); + newFile.createNewFile(); + PluginScanResult result = scan(scanner, Collections.singleton(pluginDir.toPath())); assertTrue(result.isEmpty()); } - @Test - public void testScanningPluginDirContainsInvalidJarsOnly() throws Exception { - pluginDir.newFolder("my-plugin"); - pluginDir.newFile("my-plugin/invalid.jar"); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningPluginDirContainsInvalidJarsOnly(PluginScanner scanner) throws Exception { + File newFile = new File(pluginDir, "my-plugin"); + newFile.mkdir(); + newFile = new File(newFile, "invalid.jar"); + newFile.createNewFile(); - PluginScanResult result = scan( - Collections.singleton(pluginDir.getRoot().toPath().toAbsolutePath()) - ); + PluginScanResult result = scan(scanner, Collections.singleton(pluginDir.toPath())); assertTrue(result.isEmpty()); } - @Test - public void testScanningNoPlugins() { - PluginScanResult result = scan( - Collections.singleton(pluginDir.getRoot().toPath().toAbsolutePath()) - ); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningNoPlugins(PluginScanner scanner) { + PluginScanResult result = scan(scanner, Collections.singleton(pluginDir.toPath())); assertTrue(result.isEmpty()); } - @Test - public void testScanningPluginDirEmpty() throws Exception { - pluginDir.newFolder("my-plugin"); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningPluginDirEmpty(PluginScanner scanner) { + File newFile = new File(pluginDir, "my-plugin"); + newFile.mkdir(); - PluginScanResult result = scan( - Collections.singleton(pluginDir.getRoot().toPath().toAbsolutePath()) - ); + PluginScanResult result = scan(scanner, Collections.singleton(pluginDir.toPath())); assertTrue(result.isEmpty()); } - @Test - public void testScanningMixOfValidAndInvalidPlugins() throws Exception { - pluginDir.newFile("invalid.jar"); - pluginDir.newFolder("my-plugin"); - pluginDir.newFile("my-plugin/invalid.jar"); - Path pluginPath = this.pluginDir.getRoot().toPath(); + @ParameterizedTest + @MethodSource("parameters") + public void testScanningMixOfValidAndInvalidPlugins(PluginScanner scanner) throws Exception { + new File(pluginDir, "invalid.jar").createNewFile(); + File newFile = new File(pluginDir, "my-plugin"); + newFile.mkdir(); + newFile = new File(newFile, "invalid.jar"); + newFile.createNewFile(); + Path pluginPath = this.pluginDir.toPath(); for (Path source : TestPlugins.pluginPath()) { Files.copy(source, pluginPath.resolve(source.getFileName())); } - PluginScanResult result = scan( - Collections.singleton(pluginDir.getRoot().toPath().toAbsolutePath()) - ); + PluginScanResult result = scan(scanner, Collections.singleton(pluginDir.toPath())); Set classes = new HashSet<>(); result.forEach(pluginDesc -> classes.add(pluginDesc.className())); Set expectedClasses = new HashSet<>(TestPlugins.pluginClasses()); assertEquals(expectedClasses, classes); } - @Test - public void testNonVersionedPluginHasUndefinedVersion() { - PluginScanResult unversionedPluginsResult = scan(TestPlugins.pluginPath(TestPlugins.TestPlugin.SAMPLING_HEADER_CONVERTER)); + @ParameterizedTest + @MethodSource("parameters") + public void testNonVersionedPluginHasUndefinedVersion(PluginScanner scanner) { + PluginScanResult unversionedPluginsResult = scan(scanner, + TestPlugins.pluginPath(TestPlugins.TestPlugin.SAMPLING_HEADER_CONVERTER)); assertFalse(unversionedPluginsResult.isEmpty()); unversionedPluginsResult.forEach(pluginDesc -> assertEquals(PluginDesc.UNDEFINED_VERSION, pluginDesc.version())); } - @Test - public void testVersionedPluginsHasVersion() { - PluginScanResult versionedPluginResult = scan(TestPlugins.pluginPath(TestPlugins.TestPlugin.READ_VERSION_FROM_RESOURCE_V1)); + @ParameterizedTest + @MethodSource("parameters") + public void testVersionedPluginsHasVersion(PluginScanner scanner) { + PluginScanResult versionedPluginResult = scan(scanner, + TestPlugins.pluginPath(TestPlugins.TestPlugin.READ_VERSION_FROM_RESOURCE_V1)); assertFalse(versionedPluginResult.isEmpty()); versionedPluginResult.forEach(pluginDesc -> assertEquals("1.0.0", pluginDesc.version())); } - private PluginScanResult scan(Set pluginLocations) { + private PluginScanResult scan(PluginScanner scanner, Set pluginLocations) { ClassLoaderFactory factory = new ClassLoaderFactory(); Set pluginSources = PluginUtils.pluginSources(pluginLocations, PluginScannerTest.class.getClassLoader(), factory); return scanner.discoverPlugins(pluginSources); } - -} +} \ No newline at end of file diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginUtilsTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginUtilsTest.java index f5dc83e6a89..1b2c0c06874 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginUtilsTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginUtilsTest.java @@ -28,10 +28,9 @@ import org.apache.kafka.connect.storage.HeaderConverter; import org.apache.kafka.connect.tools.MockSinkConnector; import org.apache.kafka.connect.tools.MockSourceConnector; import org.apache.kafka.connect.transforms.Transformation; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.io.TempDir; import java.io.IOException; import java.nio.file.Files; @@ -46,18 +45,21 @@ import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; public class PluginUtilsTest { - @Rule - public TemporaryFolder rootDir = new TemporaryFolder(); + @TempDir + Path rootDir; + private Path pluginPath; - @Before + @BeforeEach public void setUp() throws Exception { - pluginPath = rootDir.newFolder("plugins").toPath().toRealPath(); + pluginPath = rootDir.resolve("plugins"); + Files.createDirectories(pluginPath); + pluginPath = pluginPath.toRealPath(); } @Test @@ -190,10 +192,8 @@ public class PluginUtilsTest { ); // Classes in the API should never be loaded in isolation. for (String clazz : apiClasses) { - assertFalse( - clazz + " from 'api' is loaded in isolation but should not be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertFalse(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'api' is loaded in isolation but should not be"); } } @@ -221,10 +221,8 @@ public class PluginUtilsTest { "org.apache.kafka.connect.util." ); for (String clazz : runtimeClasses) { - assertFalse( - clazz + " from 'runtime' is loaded in isolation but should not be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertFalse(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'runtime' is loaded in isolation but should not be"); } } @@ -250,10 +248,8 @@ public class PluginUtilsTest { "org.apache.kafka.connect.storage.SimpleHeaderConverter" ); for (String clazz : jsonConverterClasses) { - assertTrue( - clazz + " from 'runtime' is not loaded in isolation but should be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertTrue(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'runtime' is not loaded in isolation but should be"); } } @@ -305,10 +301,8 @@ public class PluginUtilsTest { "org.apache.kafka.connect.transforms.predicates.TopicNameMatches" ); for (String clazz : transformsClasses) { - assertTrue( - clazz + " from 'transforms' is not loaded in isolation but should be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertTrue(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'transforms' is not loaded in isolation but should be"); } } @@ -324,10 +318,8 @@ public class PluginUtilsTest { "org.apache.kafka.connect.json.JsonSerializer" ); for (String clazz : jsonConverterClasses) { - assertTrue( - clazz + " from 'json' is not loaded in isolation but should be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertTrue(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'json' is not loaded in isolation but should be"); } } @@ -341,10 +333,8 @@ public class PluginUtilsTest { "org.apache.kafka.connect.file.FileStreamSourceTask" ); for (String clazz : jsonConverterClasses) { - assertTrue( - clazz + " from 'file' is not loaded in isolation but should be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertTrue(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'file' is not loaded in isolation but should be"); } } @@ -356,10 +346,8 @@ public class PluginUtilsTest { //"org.apache.kafka.connect.rest.basic.auth.extension.PropertyFileLoginModule" TODO fix? ); for (String clazz : basicAuthExtensionClasses) { - assertTrue( - clazz + " from 'basic-auth-extension' is not loaded in isolation but should be", - PluginUtils.shouldLoadInIsolation(clazz) - ); + assertTrue(PluginUtils.shouldLoadInIsolation(clazz), + clazz + " from 'basic-auth-extension' is not loaded in isolation but should be"); } } @@ -457,7 +445,9 @@ public class PluginUtilsTest { public void testPluginUrlsWithAbsoluteSymlink() throws Exception { createBasicDirectoryLayout(); - Path anotherPath = rootDir.newFolder("moreplugins").toPath().toRealPath(); + Path anotherPath = rootDir.resolve("moreplugins"); + Files.createDirectories(anotherPath); + anotherPath = anotherPath.toRealPath(); Files.createDirectories(anotherPath.resolve("connectorB-deps")); Files.createSymbolicLink( pluginPath.resolve("connectorB/deps/symlink"), @@ -474,7 +464,9 @@ public class PluginUtilsTest { public void testPluginUrlsWithRelativeSymlinkBackwards() throws Exception { createBasicDirectoryLayout(); - Path anotherPath = rootDir.newFolder("moreplugins").toPath().toRealPath(); + Path anotherPath = rootDir.resolve("moreplugins"); + Files.createDirectories(anotherPath); + anotherPath = anotherPath.toRealPath(); Files.createDirectories(anotherPath.resolve("connectorB-deps")); Files.createSymbolicLink( pluginPath.resolve("connectorB/deps/symlink"), diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginsTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginsTest.java index 8a637beee5e..f40df570539 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginsTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/PluginsTest.java @@ -54,8 +54,8 @@ import org.apache.kafka.connect.storage.ConverterConfig; import org.apache.kafka.connect.storage.ConverterType; import org.apache.kafka.connect.storage.HeaderConverter; import org.apache.kafka.connect.storage.SimpleHeaderConverter; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; import java.util.HashMap; import java.util.List; @@ -64,13 +64,13 @@ import java.util.Set; import java.util.SortedSet; import java.util.stream.Collectors; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +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.assertInstanceOf; public class PluginsTest { @@ -85,7 +85,7 @@ public class PluginsTest { private PluginScanResult empty; private String missingPluginClass; - @Before + @BeforeEach public void setup() { Map pluginProps = new HashMap<>(); @@ -183,10 +183,10 @@ public class PluginsTest { config, ConnectRestExtension.class); assertNotNull(connectRestExtensions); - assertEquals("One Rest Extension expected", 1, connectRestExtensions.size()); + assertEquals(1, connectRestExtensions.size(), "One Rest Extension expected"); assertNotNull(connectRestExtensions.get(0)); - assertTrue("Should be instance of TestConnectRestExtension", - connectRestExtensions.get(0) instanceof TestConnectRestExtension); + assertTrue(connectRestExtensions.get(0) instanceof TestConnectRestExtension, + "Should be instance of TestConnectRestExtension"); assertNotNull(((TestConnectRestExtension) connectRestExtensions.get(0)).configs); assertEquals(config.originals(), ((TestConnectRestExtension) connectRestExtensions.get(0)).configs); @@ -482,7 +482,7 @@ public class PluginsTest { .stream() .filter(pluginDesc -> ByteArrayConverter.class.equals(pluginDesc.pluginClass())) .collect(Collectors.toSet()); - assertFalse("Could not find superclass of " + TestPlugin.SUBCLASS_OF_CLASSPATH_CONVERTER + " as plugin", converters.isEmpty()); + assertFalse(converters.isEmpty(), "Could not find superclass of " + TestPlugin.SUBCLASS_OF_CLASSPATH_CONVERTER + " as plugin"); for (PluginDesc byteArrayConverter : converters) { assertEquals("classpath", byteArrayConverter.location()); } @@ -494,7 +494,7 @@ public class PluginsTest { .stream() .filter(pluginDesc -> AllConnectorClientConfigOverridePolicy.class.equals(pluginDesc.pluginClass())) .collect(Collectors.toSet()); - assertFalse("Could not find superclass of " + TestPlugin.SUBCLASS_OF_CLASSPATH_OVERRIDE_POLICY + " as plugin", overridePolicies.isEmpty()); + assertFalse(overridePolicies.isEmpty(), "Could not find superclass of " + TestPlugin.SUBCLASS_OF_CLASSPATH_OVERRIDE_POLICY + " as plugin"); for (PluginDesc allOverridePolicy : overridePolicies) { assertEquals("classpath", allOverridePolicy.location()); } @@ -620,10 +620,10 @@ public class PluginsTest { ); plugins = new Plugins(pluginProps, parent, new ClassLoaderFactory()); - assertTrue("Should find plugin in plugin classloader", - plugins.converters().stream().anyMatch(desc -> desc.loader() instanceof PluginClassLoader)); - assertTrue("Should find plugin in parent classloader", - plugins.converters().stream().anyMatch(desc -> parent.equals(desc.loader()))); + assertTrue(plugins.converters().stream().anyMatch(desc -> desc.loader() instanceof PluginClassLoader), + "Should find plugin in plugin classloader"); + assertTrue(plugins.converters().stream().anyMatch(desc -> parent.equals(desc.loader())), + "Should find plugin in parent classloader"); Converter converter = plugins.newPlugin( className, diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/SynchronizationTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/SynchronizationTest.java index e8ba9153bc0..963946c8290 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/SynchronizationTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/isolation/SynchronizationTest.java @@ -17,7 +17,6 @@ package org.apache.kafka.connect.runtime.isolation; -import static org.junit.Assert.fail; import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; @@ -45,36 +44,35 @@ import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; import org.apache.kafka.common.config.ConfigDef.Type; import org.apache.kafka.connect.runtime.WorkerConfig; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.Timeout; import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.fail; + public class SynchronizationTest { public static final Logger log = LoggerFactory.getLogger(SynchronizationTest.class); - @Rule - public final TestName testName = new TestName(); - private String threadPrefix; private Plugins plugins; private ThreadPoolExecutor exec; private Breakpoint dclBreakpoint; private Breakpoint pclBreakpoint; - @Before - public void setup() { + @BeforeEach + public void setup(TestInfo testInfo) { Map pluginProps = Collections.singletonMap( WorkerConfig.PLUGIN_PATH_CONFIG, TestPlugins.pluginPathJoined() ); threadPrefix = SynchronizationTest.class.getSimpleName() - + "." + testName.getMethodName() + "-"; + + "." + testInfo.getDisplayName() + "-"; dclBreakpoint = new Breakpoint<>(); pclBreakpoint = new Breakpoint<>(); plugins = new Plugins(pluginProps, Plugins.class.getClassLoader(), new SynchronizedClassLoaderFactory()); @@ -89,7 +87,7 @@ public class SynchronizationTest { } - @After + @AfterEach public void tearDown() throws InterruptedException { dclBreakpoint.clear(); pclBreakpoint.clear(); @@ -113,7 +111,6 @@ public class SynchronizationTest { public synchronized void set(Predicate predicate) { clear(); this.predicate = predicate; - // As soon as the barrier is tripped, the barrier will be reset for the next round. barrier = new CyclicBarrier(2); } @@ -125,7 +122,7 @@ public class SynchronizationTest { Predicate predicate; CyclicBarrier barrier; synchronized (this) { - predicate = this.predicate; + predicate = this.predicate; barrier = this.barrier; } if (predicate != null && !predicate.test(obj)) { @@ -206,7 +203,6 @@ public class SynchronizationTest { private final Breakpoint pclBreakpoint; - public SynchronizedPluginClassLoader( URL pluginLocation, URL[] urls, ClassLoader parent, Breakpoint pclBreakpoint ) { @@ -221,8 +217,9 @@ public class SynchronizationTest { } } + @Test + @Timeout(15) // If the test times out, then there's a deadlock in the test but not necessarily the code - @Test(timeout = 15000L) public void testSimultaneousUpwardAndDownwardDelegating() throws Exception { String t1Class = TestPlugins.TestPlugin.SAMPLING_CONVERTER.className(); // Grab a reference to the target PluginClassLoader before activating breakpoints @@ -300,8 +297,9 @@ public class SynchronizationTest { } // If the test times out, then there's a deadlock in the test but not necessarily the code - @Test(timeout = 15000L) + @Test // Ensure the PluginClassLoader is parallel capable and not synchronized on its monitor lock + @Timeout(15) public void testPluginClassLoaderDoesntHoldMonitorLock() throws InterruptedException, TimeoutException, BrokenBarrierException { String t1Class = TestPlugins.TestPlugin.SAMPLING_CONVERTER.className(); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/ConnectRestServerTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/ConnectRestServerTest.java index 0494d002726..c430e0d8869 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/ConnectRestServerTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/ConnectRestServerTest.java @@ -35,13 +35,14 @@ import org.apache.kafka.connect.rest.ConnectRestExtension; import org.apache.kafka.connect.runtime.Herder; import org.apache.kafka.connect.runtime.isolation.Plugins; import org.apache.kafka.connect.runtime.rest.entities.LoggerLevel; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.slf4j.LoggerFactory; import javax.ws.rs.core.MediaType; @@ -56,15 +57,17 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class ConnectRestServerTest { @Mock private RestClient restClient; @@ -76,12 +79,12 @@ public class ConnectRestServerTest { protected static final String KAFKA_CLUSTER_ID = "Xbafgnagvar"; - @Before + @BeforeEach public void setUp() { httpClient = HttpClients.createMinimal(); } - @After + @AfterEach public void tearDown() throws IOException { for (CloseableHttpResponse response: responses) { response.close(); @@ -117,7 +120,7 @@ public class ConnectRestServerTest { configMap.put(RestServerConfig.LISTENERS_CONFIG, "http://localhost:8080,https://localhost:8443"); server = new ConnectRestServer(null, restClient, configMap); - Assert.assertEquals("http://localhost:8080/", server.advertisedUrl().toString()); + assertEquals("http://localhost:8080/", server.advertisedUrl().toString()); server.stop(); // Advertised URI from listeners with protocol @@ -126,7 +129,7 @@ public class ConnectRestServerTest { configMap.put(RestServerConfig.REST_ADVERTISED_LISTENER_CONFIG, "https"); server = new ConnectRestServer(null, restClient, configMap); - Assert.assertEquals("https://localhost:8443/", server.advertisedUrl().toString()); + assertEquals("https://localhost:8443/", server.advertisedUrl().toString()); server.stop(); // Advertised URI from listeners with only SSL available @@ -134,7 +137,7 @@ public class ConnectRestServerTest { configMap.put(RestServerConfig.LISTENERS_CONFIG, "https://localhost:8443"); server = new ConnectRestServer(null, restClient, configMap); - Assert.assertEquals("https://localhost:8443/", server.advertisedUrl().toString()); + assertEquals("https://localhost:8443/", server.advertisedUrl().toString()); server.stop(); // Listener is overridden by advertised values @@ -145,7 +148,7 @@ public class ConnectRestServerTest { configMap.put(RestServerConfig.REST_ADVERTISED_PORT_CONFIG, "10000"); server = new ConnectRestServer(null, restClient, configMap); - Assert.assertEquals("http://somehost:10000/", server.advertisedUrl().toString()); + assertEquals("http://somehost:10000/", server.advertisedUrl().toString()); server.stop(); // correct listener is chosen when https listener is configured before http listener and advertised listener is http @@ -154,7 +157,7 @@ public class ConnectRestServerTest { configMap.put(RestServerConfig.REST_ADVERTISED_LISTENER_CONFIG, "http"); server = new ConnectRestServer(null, restClient, configMap); - Assert.assertEquals("http://plaintext-localhost:4761/", server.advertisedUrl().toString()); + assertEquals("http://plaintext-localhost:4761/", server.advertisedUrl().toString()); server.stop(); } @@ -173,10 +176,10 @@ public class ConnectRestServerTest { HttpOptions request = new HttpOptions("/connectors"); request.addHeader("Content-Type", MediaType.WILDCARD); HttpResponse response = executeRequest(server.advertisedUrl(), request); - Assert.assertEquals(MediaType.TEXT_PLAIN, response.getEntity().getContentType().getValue()); + assertEquals(MediaType.TEXT_PLAIN, response.getEntity().getContentType().getValue()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); response.getEntity().writeTo(baos); - Assert.assertArrayEquals( + assertArrayEquals( request.getAllowedMethods(response).toArray(), new String(baos.toByteArray(), StandardCharsets.UTF_8).split(", ") ); @@ -203,10 +206,10 @@ public class ConnectRestServerTest { request.addHeader("Origin", origin); HttpResponse response = executeRequest(serverUrl, request); - Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); if (expectedHeader != null) { - Assert.assertEquals(expectedHeader, + assertEquals(expectedHeader, response.getFirstHeader("Access-Control-Allow-Origin").getValue()); } @@ -215,13 +218,13 @@ public class ConnectRestServerTest { request.addHeader("Origin", origin); request.addHeader("Access-Control-Request-Method", method); response = executeRequest(serverUrl, request); - Assert.assertEquals(404, response.getStatusLine().getStatusCode()); + assertEquals(404, response.getStatusLine().getStatusCode()); if (expectedHeader != null) { - Assert.assertEquals(expectedHeader, + assertEquals(expectedHeader, response.getFirstHeader("Access-Control-Allow-Origin").getValue()); } if (method != null) { - Assert.assertEquals(method, + assertEquals(method, response.getFirstHeader("Access-Control-Allow-Methods").getValue()); } } @@ -242,7 +245,7 @@ public class ConnectRestServerTest { HttpRequest request = new HttpGet("/connectors"); HttpResponse response = executeRequest(server.advertisedUrl(), request); - Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); } @Test @@ -304,7 +307,7 @@ public class ConnectRestServerTest { HttpRequest request = new HttpGet("/admin/loggers"); HttpResponse response = executeRequest(server.advertisedUrl(), request); - Assert.assertEquals(404, response.getStatusLine().getStatusCode()); + assertEquals(404, response.getStatusLine().getStatusCode()); } @Test @@ -324,7 +327,7 @@ public class ConnectRestServerTest { HttpRequest request = new HttpGet("/admin/loggers"); HttpResponse response = executeRequest(server.advertisedUrl(), request); - Assert.assertEquals(404, response.getStatusLine().getStatusCode()); + assertEquals(404, response.getStatusLine().getStatusCode()); } @Test @@ -386,12 +389,12 @@ public class ConnectRestServerTest { server.initializeResources(herder); HttpRequest request = new HttpGet("/connectors"); HttpResponse response = executeRequest(server.advertisedUrl(), request); - Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); if (!headerConfig.isEmpty()) { expectedHeaders.forEach((k, v) -> - Assert.assertEquals(response.getFirstHeader(k).getValue(), v)); + assertEquals(response.getFirstHeader(k).getValue(), v)); } else { - Assert.assertNull(response.getFirstHeader("X-Frame-Options")); + assertNull(response.getFirstHeader("X-Frame-Options")); } } @@ -399,7 +402,7 @@ public class ConnectRestServerTest { HttpRequest request = new HttpGet(endpoint); HttpResponse response = executeRequest(serverUrl, request); - Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); return new BasicResponseHandler().handleResponse(response); } @@ -410,7 +413,7 @@ public class ConnectRestServerTest { request.setEntity(entity); HttpResponse response = executeRequest(serverUrl, request); - Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); return new BasicResponseHandler().handleResponse(response); } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/InternalRequestSignatureTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/InternalRequestSignatureTest.java index 82fab131306..0756908926b 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/InternalRequestSignatureTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/InternalRequestSignatureTest.java @@ -21,10 +21,12 @@ import org.apache.kafka.connect.errors.ConnectException; import org.apache.kafka.connect.runtime.distributed.Crypto; import org.apache.kafka.connect.runtime.rest.errors.BadRequestException; import org.eclipse.jetty.client.api.Request; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import javax.crypto.Mac; import javax.crypto.SecretKey; @@ -34,18 +36,19 @@ import javax.ws.rs.core.HttpHeaders; import java.security.NoSuchAlgorithmException; import java.util.Base64; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +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.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class InternalRequestSignatureTest { private static final byte[] REQUEST_BODY = @@ -123,16 +126,12 @@ public class InternalRequestSignatureTest { InternalRequestSignature.addToRequest(crypto, KEY, REQUEST_BODY, SIGNATURE_ALGORITHM, request); - assertEquals( - "Request should have valid base 64-encoded signature added as header", - ENCODED_SIGNATURE, - signatureCapture.getValue() - ); - assertEquals( - "Request should have provided signature algorithm added as header", - SIGNATURE_ALGORITHM, - signatureAlgorithmCapture.getValue() - ); + assertEquals(ENCODED_SIGNATURE, + signatureCapture.getValue(), + "Request should have valid base 64-encoded signature added as header"); + assertEquals(SIGNATURE_ALGORITHM, + signatureAlgorithmCapture.getValue(), + "Request should have provided signature algorithm added as header"); } @Test diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestClientTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestClientTest.java index 3c104e0e930..91211b8939b 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestClientTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestClientTest.java @@ -19,7 +19,6 @@ package org.apache.kafka.connect.runtime.rest; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.kafka.connect.runtime.rest.entities.ErrorMessage; @@ -27,25 +26,23 @@ import org.apache.kafka.connect.runtime.rest.errors.ConnectRestException; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.junit.MockitoRule; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import javax.crypto.SecretKey; import javax.ws.rs.core.Response; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -61,18 +58,21 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; -@RunWith(Enclosed.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class RestClientTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final String MOCK_URL = "http://localhost:1234/api/endpoint"; private static final String TEST_METHOD = "GET"; private static final TestDTO TEST_DTO = new TestDTO("requestBodyData"); - private static final TypeReference TEST_TYPE = new TypeReference() { - }; + private static final TypeReference TEST_TYPE = new TypeReference() { }; private static final SecretKey MOCK_SECRET_KEY = getMockSecretKey(); private static final String TEST_SIGNATURE_ALGORITHM = "HmacSHA1"; + @Mock + private HttpClient httpClient; + private static void assertIsInternalServerError(ConnectRestException e) { assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.statusCode()); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.errorCode()); @@ -80,7 +80,7 @@ public class RestClientTest { private static SecretKey getMockSecretKey() { SecretKey mockKey = mock(SecretKey.class); - when(mockKey.getFormat()).thenReturn("RAW"); // supported format by + when(mockKey.getFormat()).thenReturn("RAW"); when(mockKey.getEncoded()).thenReturn("SomeKey".getBytes(StandardCharsets.UTF_8)); return mockKey; } @@ -105,227 +105,230 @@ public class RestClientTest { ); } - - @RunWith(Parameterized.class) - public static class RequestFailureParameterizedTest { - - @Rule - public MockitoRule initRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock - private HttpClient httpClient; - - @Parameterized.Parameter - public Throwable requestException; - - @Parameterized.Parameters - public static Collection requestExceptions() { - return Arrays.asList(new Object[][]{ - {new InterruptedException()}, - {new ExecutionException(null)}, - {new TimeoutException()} - }); - } - - private static Request buildThrowingMockRequest(Throwable t) throws ExecutionException, InterruptedException, TimeoutException { - Request req = mock(Request.class); - when(req.header(anyString(), anyString())).thenReturn(req); - when(req.send()).thenThrow(t); - return req; - } - - @Test - public void testFailureDuringRequestCausesInternalServerError() throws Exception { - Request request = buildThrowingMockRequest(requestException); - when(httpClient.newRequest(anyString())).thenReturn(request); - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertIsInternalServerError(e); - assertEquals(requestException, e.getCause()); - } + private static Stream requestExceptions() { + return Stream.of( + Arguments.of(new InterruptedException()), + Arguments.of(new ExecutionException(null)), + Arguments.of(new TimeoutException()) + ); } - - @RunWith(MockitoJUnitRunner.StrictStubs.class) - public static class Tests { - @Mock - private HttpClient httpClient; - - private static String toJsonString(Object obj) { - try { - return OBJECT_MAPPER.writeValueAsString(obj); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - private void setupHttpClient(int responseCode, String responseJsonString) throws Exception { - Request req = mock(Request.class); - ContentResponse resp = mock(ContentResponse.class); - when(resp.getStatus()).thenReturn(responseCode); - when(resp.getContentAsString()).thenReturn(responseJsonString); - when(req.send()).thenReturn(resp); - when(req.header(anyString(), anyString())).thenReturn(req); - when(httpClient.newRequest(anyString())).thenReturn(req); - } - - @Test - public void testNullUrl() throws Exception { - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - assertThrows(NullPointerException.class, () -> httpRequest( - httpClient, null, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - } - - @Test - public void testNullMethod() throws Exception { - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - assertThrows(NullPointerException.class, () -> httpRequest( - httpClient, MOCK_URL, null, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - } - - @Test - public void testNullResponseType() throws Exception { - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - assertThrows(NullPointerException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, null, TEST_SIGNATURE_ALGORITHM - )); - } - - @Test - public void testSuccess() throws Exception { - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - RestClient.HttpResponse httpResp = httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - ); - assertEquals(statusCode, httpResp.status()); - assertEquals(TEST_DTO, httpResp.body()); - } - - @Test - public void testNoContent() throws Exception { - int statusCode = Response.Status.NO_CONTENT.getStatusCode(); - setupHttpClient(statusCode, null); - - RestClient.HttpResponse httpResp = httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - ); - assertEquals(statusCode, httpResp.status()); - assertNull(httpResp.body()); - } - - @Test - public void testStatusCodeAndErrorMessagePreserved() throws Exception { - int statusCode = Response.Status.CONFLICT.getStatusCode(); - ErrorMessage errorMsg = new ErrorMessage(Response.Status.GONE.getStatusCode(), "Some Error Message"); - setupHttpClient(statusCode, toJsonString(errorMsg)); - - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertEquals(statusCode, e.statusCode()); - assertEquals(errorMsg.errorCode(), e.errorCode()); - assertEquals(errorMsg.message(), e.getMessage()); - } - - @Test - public void testNonEmptyResponseWithVoidResponseType() throws Exception { - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - TypeReference voidResponse = new TypeReference() { }; - RestClient.HttpResponse httpResp = httpRequest( - httpClient, MOCK_URL, TEST_METHOD, voidResponse, TEST_SIGNATURE_ALGORITHM - ); - assertEquals(statusCode, httpResp.status()); - assertNull(httpResp.body()); - } - - @Test - public void testUnexpectedHttpResponseCausesInternalServerError() throws Exception { - int statusCode = Response.Status.NOT_MODIFIED.getStatusCode(); // never thrown explicitly - - // should be treated as an unexpected error and translated into 500 INTERNAL_SERVER_ERROR - - setupHttpClient(statusCode, null); - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertIsInternalServerError(e); - } - - @Test - public void testRuntimeExceptionCausesInternalServerError() { - when(httpClient.newRequest(anyString())).thenThrow(new RuntimeException()); - - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertIsInternalServerError(e); - } - - @Test - public void testRequestSignatureFailureCausesInternalServerError() throws Exception { - setupHttpClient(0, null); - - String invalidRequestSignatureAlgorithm = "Foo"; - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, invalidRequestSignatureAlgorithm - )); - assertIsInternalServerError(e); - } - - @Test - public void testIOExceptionCausesInternalServerError() throws Exception { - String invalidJsonString = "Invalid"; - setupHttpClient(201, invalidJsonString); - - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertIsInternalServerError(e); - } - - @Test - public void testUseSslConfigsOnlyWhenNecessary() throws Exception { - // See KAFKA-14816; we want to make sure that even if the worker is configured with invalid SSL properties, - // REST requests only fail if we try to contact a URL using HTTPS (but not HTTP) - int statusCode = Response.Status.OK.getStatusCode(); - setupHttpClient(statusCode, toJsonString(TEST_DTO)); - - assertDoesNotThrow(() -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - String httpsUrl = "https://localhost:1234/api/endpoint"; - assertThrows(RuntimeException.class, () -> httpRequest( - httpClient, httpsUrl, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - } - - @Test - public void testHttpRequestInterrupted() throws ExecutionException, InterruptedException, TimeoutException { - Request req = mock(Request.class); - doThrow(new InterruptedException()).when(req).send(); - doReturn(req).when(req).header(anyString(), anyString()); - doReturn(req).when(httpClient).newRequest(anyString()); - ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( - httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM - )); - assertIsInternalServerError(e); - assertInstanceOf(InterruptedException.class, e.getCause()); - assertTrue(Thread.interrupted()); - } + private static Request buildThrowingMockRequest(Throwable t) throws ExecutionException, InterruptedException, TimeoutException { + Request req = mock(Request.class); + when(req.header(anyString(), anyString())).thenReturn(req); + when(req.send()).thenThrow(t); + return req; } + @ParameterizedTest + @MethodSource("requestExceptions") + public void testFailureDuringRequestCausesInternalServerError(Throwable requestException) throws Exception { + Request request = buildThrowingMockRequest(requestException); + when(httpClient.newRequest(anyString())).thenReturn(request); + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertIsInternalServerError(e); + assertEquals(requestException, e.getCause()); + } + + @Test + public void testNullUrl() { + RestClient client = spy(new RestClient(null)); + assertThrows(NullPointerException.class, () -> { + client.httpRequest( + null, + TEST_METHOD, + null, + TEST_DTO, + TEST_TYPE, + MOCK_SECRET_KEY, + TEST_SIGNATURE_ALGORITHM + ); + }); + } + + @Test + public void testNullMethod() { + RestClient client = spy(new RestClient(null)); + assertThrows(NullPointerException.class, () -> client.httpRequest( + MOCK_URL, + null, + null, + TEST_DTO, + TEST_TYPE, + MOCK_SECRET_KEY, + TEST_SIGNATURE_ALGORITHM + )); + } + + @Test + public void testNullResponseType() { + RestClient client = spy(new RestClient(null)); + assertThrows(NullPointerException.class, () -> client.httpRequest( + MOCK_URL, + TEST_METHOD, + null, + TEST_DTO, + null, + MOCK_SECRET_KEY, + TEST_SIGNATURE_ALGORITHM + )); + } + + @Test + public void testSuccess() throws Exception { + int statusCode = Response.Status.OK.getStatusCode(); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + when(resp.getContentAsString()).thenReturn(toJsonString(TEST_DTO)); + setupHttpClient(statusCode, req, resp); + + RestClient.HttpResponse httpResp = httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + ); + assertEquals(statusCode, httpResp.status()); + assertEquals(TEST_DTO, httpResp.body()); + } + + @Test + public void testNoContent() throws Exception { + int statusCode = Response.Status.NO_CONTENT.getStatusCode(); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + setupHttpClient(statusCode, req, resp); + + RestClient.HttpResponse httpResp = httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + ); + assertEquals(statusCode, httpResp.status()); + assertNull(httpResp.body()); + } + + @Test + public void testStatusCodeAndErrorMessagePreserved() throws Exception { + int statusCode = Response.Status.CONFLICT.getStatusCode(); + ErrorMessage errorMsg = new ErrorMessage(Response.Status.GONE.getStatusCode(), "Some Error Message"); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + when(resp.getContentAsString()).thenReturn(toJsonString(errorMsg)); + setupHttpClient(statusCode, req, resp); + + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertEquals(statusCode, e.statusCode()); + assertEquals(errorMsg.errorCode(), e.errorCode()); + assertEquals(errorMsg.message(), e.getMessage()); + } + + @Test + public void testNonEmptyResponseWithVoidResponseType() throws Exception { + int statusCode = Response.Status.OK.getStatusCode(); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + when(resp.getContentAsString()).thenReturn(toJsonString(TEST_DTO)); + setupHttpClient(statusCode, req, resp); + + TypeReference voidResponse = new TypeReference() { }; + RestClient.HttpResponse httpResp = httpRequest( + httpClient, MOCK_URL, TEST_METHOD, voidResponse, TEST_SIGNATURE_ALGORITHM + ); + assertEquals(statusCode, httpResp.status()); + assertNull(httpResp.body()); + } + + @Test + public void testUnexpectedHttpResponseCausesInternalServerError() throws Exception { + int statusCode = Response.Status.NOT_MODIFIED.getStatusCode(); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + + setupHttpClient(statusCode, req, resp); + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertIsInternalServerError(e); + } + + @Test + public void testRuntimeExceptionCausesInternalServerError() { + when(httpClient.newRequest(anyString())).thenThrow(new RuntimeException()); + + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertIsInternalServerError(e); + } + + @Test + public void testRequestSignatureFailureCausesInternalServerError() { + String invalidRequestSignatureAlgorithm = "Foo"; + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, invalidRequestSignatureAlgorithm + )); + assertIsInternalServerError(e); + } + + @Test + public void testIOExceptionCausesInternalServerError() throws Exception { + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + setupHttpClient(201, req, resp); + + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertIsInternalServerError(e); + } + + @Test + public void testUseSslConfigsOnlyWhenNecessary() throws Exception { + int statusCode = Response.Status.OK.getStatusCode(); + Request req = mock(Request.class); + ContentResponse resp = mock(ContentResponse.class); + when(resp.getContentAsString()).thenReturn(toJsonString(TEST_DTO)); + setupHttpClient(statusCode, req, resp); + assertDoesNotThrow(() -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + String httpsUrl = "https://localhost:1234/api/endpoint"; + RestClient client = spy(new RestClient(null)); + assertThrows(RuntimeException.class, () -> client.httpRequest( + httpsUrl, + TEST_METHOD, + null, + TEST_DTO, + TEST_TYPE, + MOCK_SECRET_KEY, + TEST_SIGNATURE_ALGORITHM + )); + } + + @Test + public void testHttpRequestInterrupted() throws ExecutionException, InterruptedException, TimeoutException { + Request req = mock(Request.class); + doThrow(new InterruptedException()).when(req).send(); + doReturn(req).when(req).header(anyString(), anyString()); + doReturn(req).when(httpClient).newRequest(anyString()); + ConnectRestException e = assertThrows(ConnectRestException.class, () -> httpRequest( + httpClient, MOCK_URL, TEST_METHOD, TEST_TYPE, TEST_SIGNATURE_ALGORITHM + )); + assertIsInternalServerError(e); + assertInstanceOf(InterruptedException.class, e.getCause()); + assertTrue(Thread.interrupted()); + } + + private void setupHttpClient(int responseCode, Request req, ContentResponse resp) throws Exception { + when(resp.getStatus()).thenReturn(responseCode); + when(req.send()).thenReturn(resp); + when(req.header(anyString(), anyString())).thenReturn(req); + when(httpClient.newRequest(anyString())).thenReturn(req); + } + + private String toJsonString(Object obj) { + return assertDoesNotThrow(() -> OBJECT_MAPPER.writeValueAsString(obj)); + } private static class TestDTO { private final String content; @@ -352,4 +355,4 @@ public class RestClientTest { return Objects.hash(content); } } -} +} \ No newline at end of file diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestServerConfigTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestServerConfigTest.java index 4930c1a3ef2..a2373204455 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestServerConfigTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/RestServerConfigTest.java @@ -18,7 +18,7 @@ package org.apache.kafka.connect.runtime.rest; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.internals.BrokerSecurityConfigs; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; @@ -27,10 +27,10 @@ import java.util.List; import java.util.Map; import static org.apache.kafka.connect.runtime.rest.RestServerConfig.LISTENERS_DEFAULT; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class RestServerConfigTest { @@ -106,7 +106,7 @@ public class RestServerConfigTest { // no value set for "admin.listeners" RestServerConfig config = RestServerConfig.forPublic(null, props); - assertNull("Default value should be null.", config.adminListeners()); + assertNull(config.adminListeners(), "Default value should be null."); props.put(RestServerConfig.ADMIN_LISTENERS_CONFIG, ""); config = RestServerConfig.forPublic(null, props); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorOffsetsTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorOffsetsTest.java index 726915d2e3a..9731dd69697 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorOffsetsTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorOffsetsTest.java @@ -16,13 +16,13 @@ */ package org.apache.kafka.connect.runtime.rest.entities; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class ConnectorOffsetsTest { diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorTypeTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorTypeTest.java index cd07bd85573..878b838252d 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorTypeTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/ConnectorTypeTest.java @@ -16,11 +16,11 @@ */ package org.apache.kafka.connect.runtime.rest.entities; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; public class ConnectorTypeTest { diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/CreateConnectorRequestTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/CreateConnectorRequestTest.java index 1d32479f82c..8fd12cb9c65 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/CreateConnectorRequestTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/CreateConnectorRequestTest.java @@ -17,12 +17,12 @@ package org.apache.kafka.connect.runtime.rest.entities; import org.apache.kafka.connect.runtime.TargetState; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class CreateConnectorRequestTest { diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/PluginInfoTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/PluginInfoTest.java index 34e28ee47f6..c18fa20db71 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/PluginInfoTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/entities/PluginInfoTest.java @@ -17,7 +17,7 @@ package org.apache.kafka.connect.runtime.rest.entities; import org.apache.kafka.connect.runtime.isolation.PluginDesc; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorPluginsResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorPluginsResourceTest.java index 589dfb29bd0..5cf57714352 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorPluginsResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorPluginsResourceTest.java @@ -59,11 +59,13 @@ import org.apache.kafka.connect.transforms.TimestampConverter; import org.apache.kafka.connect.transforms.predicates.HasHeaderKey; import org.apache.kafka.connect.transforms.predicates.RecordIsTombstone; import org.apache.kafka.connect.util.Callback; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import javax.ws.rs.BadRequestException; import java.net.URL; @@ -83,10 +85,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Arrays.asList; -import static org.junit.Assert.assertEquals; -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.assertEquals; +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.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; @@ -97,7 +99,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class ConnectorPluginsResourceTest { private static final Map PROPS; @@ -201,7 +204,7 @@ public class ConnectorPluginsResourceTest { private final Plugins plugins = mock(Plugins.class); private ConnectorPluginsResource connectorPluginsResource; - @Before + @BeforeEach public void setUp() throws Exception { doReturn(plugins).when(herder).plugins(); doReturn(SINK_CONNECTOR_PLUGINS).when(plugins).sinkConnectors(); diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java index 2386b2558e1..5a6a47a4f2a 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java @@ -42,14 +42,15 @@ import org.apache.kafka.connect.runtime.rest.entities.TaskInfo; import org.apache.kafka.connect.runtime.rest.errors.ConnectRestException; import org.apache.kafka.connect.util.Callback; import org.apache.kafka.connect.util.ConnectorTaskId; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.mockito.stubbing.Stubber; import javax.ws.rs.BadRequestException; @@ -69,9 +70,9 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; @@ -83,7 +84,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) @SuppressWarnings("unchecked") public class ConnectorsResourceTest { // Note trailing / and that we do *not* use LEADER_URL to construct our reference values. This checks that we handle @@ -166,18 +168,15 @@ public class ConnectorsResourceTest { @Mock private RestServerConfig serverConfig; - @Before + @BeforeEach public void setUp() throws NoSuchMethodException { when(serverConfig.topicTrackingEnabled()).thenReturn(true); when(serverConfig.topicTrackingResetEnabled()).thenReturn(true); connectorsResource = new ConnectorsResource(herder, serverConfig, restClient, REQUEST_TIMEOUT); forward = mock(UriInfo.class); - MultivaluedMap queryParams = new MultivaluedHashMap<>(); - queryParams.putSingle("forward", "true"); - when(forward.getQueryParameters()).thenReturn(queryParams); } - @After + @AfterEach public void teardown() { verifyNoMoreInteractions(herder); } @@ -188,6 +187,9 @@ public class ConnectorsResourceTest { @Test public void testListConnectors() { + MultivaluedMap queryParams = new MultivaluedHashMap<>(); + queryParams.putSingle("forward", "true"); + when(forward.getQueryParameters()).thenReturn(queryParams); when(herder.connectors()).thenReturn(Arrays.asList(CONNECTOR2_NAME, CONNECTOR_NAME)); Collection connectors = (Collection) connectorsResource.listConnectors(forward, NULL_HEADERS).getEntity(); @@ -539,7 +541,7 @@ public class ConnectorsResourceTest { String rspLocation = connectorsResource.createConnector(FORWARD, NULL_HEADERS, body).getLocation().toString(); String decoded = new URI(rspLocation).getPath(); - Assert.assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded); + assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded); } @Test @@ -554,7 +556,7 @@ public class ConnectorsResourceTest { String rspLocation = connectorsResource.createConnector(FORWARD, NULL_HEADERS, body).getLocation().toString(); String decoded = new URI(rspLocation).getPath(); - Assert.assertEquals("/connectors/" + CONNECTOR_NAME_CONTROL_SEQUENCES1, decoded); + assertEquals("/connectors/" + CONNECTOR_NAME_CONTROL_SEQUENCES1, decoded); } @Test @@ -567,7 +569,7 @@ public class ConnectorsResourceTest { String rspLocation = connectorsResource.putConnectorConfig(CONNECTOR_NAME_SPECIAL_CHARS, NULL_HEADERS, FORWARD, CONNECTOR_CONFIG_SPECIAL_CHARS).getLocation().toString(); String decoded = new URI(rspLocation).getPath(); - Assert.assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded); + assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded); } @Test @@ -580,7 +582,7 @@ public class ConnectorsResourceTest { String rspLocation = connectorsResource.putConnectorConfig(CONNECTOR_NAME_CONTROL_SEQUENCES1, NULL_HEADERS, FORWARD, CONNECTOR_CONFIG_CONTROL_SEQUENCES).getLocation().toString(); String decoded = new URI(rspLocation).getPath(); - Assert.assertEquals("/connectors/" + CONNECTOR_NAME_CONTROL_SEQUENCES1, decoded); + assertEquals("/connectors/" + CONNECTOR_NAME_CONTROL_SEQUENCES1, decoded); } @Test diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/InternalConnectResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/InternalConnectResourceTest.java index c48b60fbd96..9c51e941e5b 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/InternalConnectResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/InternalConnectResourceTest.java @@ -23,12 +23,14 @@ import org.apache.kafka.connect.runtime.rest.InternalRequestSignature; import org.apache.kafka.connect.runtime.rest.RestClient; import org.apache.kafka.connect.runtime.rest.RestServer; import org.apache.kafka.connect.util.Callback; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.mockito.stubbing.Stubber; import javax.crypto.Mac; @@ -41,8 +43,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.eq; @@ -50,7 +52,8 @@ import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class InternalConnectResourceTest { private static final Boolean FORWARD = true; @@ -73,7 +76,7 @@ public class InternalConnectResourceTest { private InternalConnectResource internalResource; - @Before + @BeforeEach public void setup() { internalResource = new InternalConnectResource(herder, restClient, () -> RestServer.DEFAULT_REST_REQUEST_TIMEOUT_MS); internalResource.uriInfo = uriInfo; diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/LoggingResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/LoggingResourceTest.java index 3b3df993511..8f61568cb6b 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/LoggingResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/LoggingResourceTest.java @@ -21,11 +21,13 @@ import org.apache.kafka.connect.errors.NotFoundException; import org.apache.kafka.connect.runtime.Herder; import org.apache.kafka.connect.runtime.rest.entities.LoggerLevel; import org.apache.kafka.connect.runtime.rest.errors.BadRequestException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.slf4j.event.Level; import javax.ws.rs.core.Response; @@ -33,13 +35,14 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class LoggingResourceTest { private LoggingResource loggingResource; @@ -47,7 +50,7 @@ public class LoggingResourceTest { @Mock private Herder herder; - @Before + @BeforeEach public void setup() { loggingResource = new LoggingResource(herder); } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/RootResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/RootResourceTest.java index 97648439245..ec28e556ca0 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/RootResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/RootResourceTest.java @@ -20,23 +20,26 @@ import org.apache.kafka.clients.admin.MockAdminClient; import org.apache.kafka.common.utils.AppInfoParser; import org.apache.kafka.connect.runtime.Herder; import org.apache.kafka.connect.runtime.rest.entities.ServerInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) public class RootResourceTest { @Mock private Herder herder; private RootResource rootResource; - @Before + @BeforeEach public void setUp() { rootResource = new RootResource(herder); } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/util/SSLUtilsTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/util/SSLUtilsTest.java index 8f5c3235e7e..0a79352b899 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/util/SSLUtilsTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/util/SSLUtilsTest.java @@ -19,13 +19,17 @@ package org.apache.kafka.connect.runtime.rest.util; import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.connect.runtime.rest.RestServerConfig; import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class SSLUtilsTest { @Test @@ -37,8 +41,8 @@ public class SSLUtilsTest { Map map = new HashMap<>(); map.put("exists", "value"); - Assert.assertEquals(SSLUtils.getOrDefault(map, existingKey, defaultValue), value); - Assert.assertEquals(SSLUtils.getOrDefault(map, missingKey, defaultValue), defaultValue); + assertEquals(SSLUtils.getOrDefault(map, existingKey, defaultValue), value); + assertEquals(SSLUtils.getOrDefault(map, missingKey, defaultValue), defaultValue); } @Test @@ -64,19 +68,19 @@ public class SSLUtilsTest { RestServerConfig config = RestServerConfig.forPublic(null, configMap); SslContextFactory.Server ssl = SSLUtils.createServerSideSslContextFactory(config); - Assert.assertEquals("file:///path/to/keystore", ssl.getKeyStorePath()); - Assert.assertEquals("file:///path/to/truststore", ssl.getTrustStorePath()); - Assert.assertEquals("SunJSSE", ssl.getProvider()); - Assert.assertArrayEquals(new String[] {"SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_MD5"}, ssl.getIncludeCipherSuites()); - Assert.assertEquals("SHA1PRNG", ssl.getSecureRandomAlgorithm()); - Assert.assertTrue(ssl.getNeedClientAuth()); - Assert.assertFalse(ssl.getWantClientAuth()); - Assert.assertEquals("JKS", ssl.getKeyStoreType()); - Assert.assertEquals("JKS", ssl.getTrustStoreType()); - Assert.assertEquals("TLS", ssl.getProtocol()); - Assert.assertArrayEquals(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"}, ssl.getIncludeProtocols()); - Assert.assertEquals("SunX509", ssl.getKeyManagerFactoryAlgorithm()); - Assert.assertEquals("PKIX", ssl.getTrustManagerFactoryAlgorithm()); + assertEquals("file:///path/to/keystore", ssl.getKeyStorePath()); + assertEquals("file:///path/to/truststore", ssl.getTrustStorePath()); + assertEquals("SunJSSE", ssl.getProvider()); + assertArrayEquals(new String[] {"SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_MD5"}, ssl.getIncludeCipherSuites()); + assertEquals("SHA1PRNG", ssl.getSecureRandomAlgorithm()); + assertTrue(ssl.getNeedClientAuth()); + assertFalse(ssl.getWantClientAuth()); + assertEquals("JKS", ssl.getKeyStoreType()); + assertEquals("JKS", ssl.getTrustStoreType()); + assertEquals("TLS", ssl.getProtocol()); + assertArrayEquals(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"}, ssl.getIncludeProtocols()); + assertEquals("SunX509", ssl.getKeyManagerFactoryAlgorithm()); + assertEquals("PKIX", ssl.getTrustManagerFactoryAlgorithm()); } @Test @@ -102,17 +106,17 @@ public class SSLUtilsTest { RestServerConfig config = RestServerConfig.forPublic(null, configMap); SslContextFactory.Client ssl = SSLUtils.createClientSideSslContextFactory(config); - Assert.assertEquals("file:///path/to/keystore", ssl.getKeyStorePath()); - Assert.assertEquals("file:///path/to/truststore", ssl.getTrustStorePath()); - Assert.assertEquals("SunJSSE", ssl.getProvider()); - Assert.assertArrayEquals(new String[] {"SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_MD5"}, ssl.getIncludeCipherSuites()); - Assert.assertEquals("SHA1PRNG", ssl.getSecureRandomAlgorithm()); - Assert.assertEquals("JKS", ssl.getKeyStoreType()); - Assert.assertEquals("JKS", ssl.getTrustStoreType()); - Assert.assertEquals("TLS", ssl.getProtocol()); - Assert.assertArrayEquals(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"}, ssl.getIncludeProtocols()); - Assert.assertEquals("SunX509", ssl.getKeyManagerFactoryAlgorithm()); - Assert.assertEquals("PKIX", ssl.getTrustManagerFactoryAlgorithm()); + assertEquals("file:///path/to/keystore", ssl.getKeyStorePath()); + assertEquals("file:///path/to/truststore", ssl.getTrustStorePath()); + assertEquals("SunJSSE", ssl.getProvider()); + assertArrayEquals(new String[] {"SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_MD5"}, ssl.getIncludeCipherSuites()); + assertEquals("SHA1PRNG", ssl.getSecureRandomAlgorithm()); + assertEquals("JKS", ssl.getKeyStoreType()); + assertEquals("JKS", ssl.getTrustStoreType()); + assertEquals("TLS", ssl.getProtocol()); + assertArrayEquals(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"}, ssl.getIncludeProtocols()); + assertEquals("SunX509", ssl.getKeyManagerFactoryAlgorithm()); + assertEquals("PKIX", ssl.getTrustManagerFactoryAlgorithm()); } @Test @@ -130,14 +134,14 @@ public class SSLUtilsTest { RestServerConfig config = RestServerConfig.forPublic(null, configMap); SslContextFactory.Server ssl = SSLUtils.createServerSideSslContextFactory(config); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE, ssl.getKeyStoreType()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE, ssl.getTrustStoreType()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_PROTOCOL, ssl.getProtocol()); - Assert.assertArrayEquals(Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split("\\s*,\\s*")).toArray(), ssl.getIncludeProtocols()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ssl.getKeyManagerFactoryAlgorithm()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ssl.getTrustManagerFactoryAlgorithm()); - Assert.assertFalse(ssl.getNeedClientAuth()); - Assert.assertFalse(ssl.getWantClientAuth()); + assertEquals(SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE, ssl.getKeyStoreType()); + assertEquals(SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE, ssl.getTrustStoreType()); + assertEquals(SslConfigs.DEFAULT_SSL_PROTOCOL, ssl.getProtocol()); + assertArrayEquals(Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split("\\s*,\\s*")).toArray(), ssl.getIncludeProtocols()); + assertEquals(SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ssl.getKeyManagerFactoryAlgorithm()); + assertEquals(SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ssl.getTrustManagerFactoryAlgorithm()); + assertFalse(ssl.getNeedClientAuth()); + assertFalse(ssl.getWantClientAuth()); } @Test @@ -155,11 +159,11 @@ public class SSLUtilsTest { RestServerConfig config = RestServerConfig.forPublic(null, configMap); SslContextFactory.Client ssl = SSLUtils.createClientSideSslContextFactory(config); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE, ssl.getKeyStoreType()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE, ssl.getTrustStoreType()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_PROTOCOL, ssl.getProtocol()); - Assert.assertArrayEquals(Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split("\\s*,\\s*")).toArray(), ssl.getIncludeProtocols()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ssl.getKeyManagerFactoryAlgorithm()); - Assert.assertEquals(SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ssl.getTrustManagerFactoryAlgorithm()); + assertEquals(SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE, ssl.getKeyStoreType()); + assertEquals(SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE, ssl.getTrustStoreType()); + assertEquals(SslConfigs.DEFAULT_SSL_PROTOCOL, ssl.getProtocol()); + assertArrayEquals(Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split("\\s*,\\s*")).toArray(), ssl.getIncludeProtocols()); + assertEquals(SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ssl.getKeyManagerFactoryAlgorithm()); + assertEquals(SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ssl.getTrustManagerFactoryAlgorithm()); } } diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneConfigTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneConfigTest.java index e2e886f7925..713ea56b202 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneConfigTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneConfigTest.java @@ -20,13 +20,13 @@ import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.SslConfigs; import org.apache.kafka.common.config.types.Password; import org.apache.kafka.connect.runtime.WorkerConfig; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class StandaloneConfigTest { diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneHerderTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneHerderTest.java index 959e4989310..21062916382 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneHerderTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/standalone/StandaloneHerderTest.java @@ -60,13 +60,14 @@ import org.apache.kafka.connect.storage.StatusBackingStore; import org.apache.kafka.connect.util.Callback; import org.apache.kafka.connect.util.ConnectorTaskId; import org.apache.kafka.connect.util.FutureCallback; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import java.util.ArrayList; import java.util.Collection; @@ -87,11 +88,10 @@ import static java.util.Collections.singletonMap; import static org.apache.kafka.connect.runtime.TopicCreationConfig.DEFAULT_TOPIC_CREATION_PREFIX; import static org.apache.kafka.connect.runtime.TopicCreationConfig.PARTITIONS_CONFIG; import static org.apache.kafka.connect.runtime.TopicCreationConfig.REPLICATION_FACTOR_CONFIG; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -110,7 +110,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -@RunWith(MockitoJUnitRunner.StrictStubs.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.STRICT_STUBS) @SuppressWarnings("unchecked") public class StandaloneHerderTest { private static final String CONNECTOR_NAME = "test"; @@ -139,19 +140,19 @@ public class StandaloneHerderTest { @Mock protected StatusBackingStore statusBackingStore; private final SampleConnectorClientConfigOverridePolicy - noneConnectorClientConfigOverridePolicy = new SampleConnectorClientConfigOverridePolicy(); + noneConnectorClientConfigOverridePolicy = new SampleConnectorClientConfigOverridePolicy(); - @Before - public void setup() throws ExecutionException, InterruptedException { + public void initialize(boolean mockTransform) { herder = mock(StandaloneHerder.class, withSettings() - .useConstructor(worker, WORKER_ID, KAFKA_CLUSTER_ID, statusBackingStore, new MemoryConfigBackingStore(transformer), noneConnectorClientConfigOverridePolicy, new MockTime()) - .defaultAnswer(CALLS_REAL_METHODS)); + .useConstructor(worker, WORKER_ID, KAFKA_CLUSTER_ID, statusBackingStore, new MemoryConfigBackingStore(transformer), noneConnectorClientConfigOverridePolicy, new MockTime()) + .defaultAnswer(CALLS_REAL_METHODS)); createCallback = new FutureCallback<>(); final ArgumentCaptor> configCapture = ArgumentCaptor.forClass(Map.class); - when(transformer.transform(eq(CONNECTOR_NAME), configCapture.capture())).thenAnswer(invocation -> configCapture.getValue()); + if (mockTransform) + when(transformer.transform(eq(CONNECTOR_NAME), configCapture.capture())).thenAnswer(invocation -> configCapture.getValue()); } - @After + @AfterEach public void tearDown() { verifyNoMoreInteractions(worker, statusBackingStore); herder.stop(); @@ -159,6 +160,7 @@ public class StandaloneHerderTest { @Test public void testCreateSourceConnector() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map config = connectorConfig(SourceSink.SOURCE); @@ -171,6 +173,7 @@ public class StandaloneHerderTest { @Test public void testCreateConnectorFailedValidation() { + initialize(false); // Basic validation should be performed and return an error, but should still evaluate the connector's config Map config = connectorConfig(SourceSink.SOURCE); @@ -201,6 +204,7 @@ public class StandaloneHerderTest { @Test public void testCreateConnectorAlreadyExists() throws Throwable { + initialize(true); // First addition should succeed expectAdd(SourceSink.SOURCE); @@ -224,6 +228,7 @@ public class StandaloneHerderTest { @Test public void testCreateSinkConnector() throws Exception { + initialize(true); expectAdd(SourceSink.SINK); Map config = connectorConfig(SourceSink.SINK); @@ -236,6 +241,7 @@ public class StandaloneHerderTest { @Test public void testCreateConnectorWithStoppedInitialState() throws Exception { + initialize(true); Map config = connectorConfig(SourceSink.SINK); expectConfigValidation(SourceSink.SINK, config); @@ -248,14 +254,15 @@ public class StandaloneHerderTest { herder.putConnectorConfig(CONNECTOR_NAME, config, TargetState.STOPPED, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); assertEquals( - new ConnectorInfo(CONNECTOR_NAME, connectorConfig(SourceSink.SINK), Collections.emptyList(), ConnectorType.SINK), - connectorInfo.result() + new ConnectorInfo(CONNECTOR_NAME, connectorConfig(SourceSink.SINK), Collections.emptyList(), ConnectorType.SINK), + connectorInfo.result() ); verify(loaderSwap).close(); } @Test public void testDestroyConnector() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map config = connectorConfig(SourceSink.SOURCE); @@ -279,16 +286,17 @@ public class StandaloneHerderTest { FutureCallback> failedDeleteCallback = new FutureCallback<>(); herder.deleteConnectorConfig(CONNECTOR_NAME, failedDeleteCallback); ExecutionException e = assertThrows( - "Should have thrown NotFoundException", - ExecutionException.class, - () -> failedDeleteCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS) + ExecutionException.class, + () -> failedDeleteCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS), + "Should have thrown NotFoundException" ); assertInstanceOf(NotFoundException.class, e.getCause()); } @Test public void testRestartConnectorSameTaskConfigs() throws Exception { - expectAdd(SourceSink.SOURCE); + initialize(true); + expectAdd(SourceSink.SOURCE, false); Map config = connectorConfig(SourceSink.SOURCE); expectConfigValidation(SourceSink.SOURCE, config); @@ -299,7 +307,7 @@ public class StandaloneHerderTest { when(worker.getPlugins()).thenReturn(plugins); // same task configs as earlier, so don't expect a new set of tasks to be brought up when(worker.connectorTaskConfigs(CONNECTOR_NAME, new SourceConnectorConfig(plugins, config, true))) - .thenReturn(Collections.singletonList(taskConfig(SourceSink.SOURCE))); + .thenReturn(Collections.singletonList(taskConfig(SourceSink.SOURCE))); herder.putConnectorConfig(CONNECTOR_NAME, config, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -313,6 +321,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorNewTaskConfigs() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map config = connectorConfig(SourceSink.SOURCE); @@ -331,7 +340,7 @@ public class StandaloneHerderTest { Map taskConfigs = taskConfig(SourceSink.SOURCE); taskConfigs.put("k", "v"); when(worker.connectorTaskConfigs(CONNECTOR_NAME, new SourceConnectorConfig(plugins, config, true))) - .thenReturn(Collections.singletonList(taskConfigs)); + .thenReturn(Collections.singletonList(taskConfigs)); when(worker.startSourceTask(eq(new ConnectorTaskId(CONNECTOR_NAME, 0)), any(), eq(connectorConfig(SourceSink.SOURCE)), eq(taskConfigs), eq(herder), eq(TargetState.STARTED))).thenReturn(true); @@ -344,6 +353,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorFailureOnStart() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map config = connectorConfig(SourceSink.SOURCE); @@ -360,16 +370,13 @@ public class StandaloneHerderTest { FutureCallback restartCallback = new FutureCallback<>(); mockStartConnector(config, null, TargetState.STARTED, exception); herder.restartConnector(CONNECTOR_NAME, restartCallback); - try { - restartCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); - fail(); - } catch (ExecutionException e) { - assertEquals(exception, e.getCause()); - } + ExecutionException e = assertThrows(ExecutionException.class, () -> restartCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); + assertEquals(exception, e.getCause()); } @Test public void testRestartTask() throws Exception { + initialize(true); ConnectorTaskId taskId = new ConnectorTaskId(CONNECTOR_NAME, 0); expectAdd(SourceSink.SOURCE); @@ -380,20 +387,20 @@ public class StandaloneHerderTest { doNothing().when(worker).stopAndAwaitTask(taskId); ClusterConfigState configState = new ClusterConfigState( - -1, - null, - Collections.singletonMap(CONNECTOR_NAME, 1), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), - Collections.singletonMap(taskId, taskConfig(SourceSink.SOURCE)), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - new HashSet<>(), - new HashSet<>(), - transformer); + -1, + null, + Collections.singletonMap(CONNECTOR_NAME, 1), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), + Collections.singletonMap(taskId, taskConfig(SourceSink.SOURCE)), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + new HashSet<>(), + new HashSet<>(), + transformer); when(worker.startSourceTask(taskId, configState, connectorConfig, taskConfig(SourceSink.SOURCE), herder, TargetState.STARTED)) - .thenReturn(true); + .thenReturn(true); herder.putConnectorConfig(CONNECTOR_NAME, connectorConfig, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -407,6 +414,7 @@ public class StandaloneHerderTest { @Test public void testRestartTaskFailureOnStart() throws Exception { + initialize(true); ConnectorTaskId taskId = new ConnectorTaskId(CONNECTOR_NAME, 0); expectAdd(SourceSink.SOURCE); @@ -414,20 +422,20 @@ public class StandaloneHerderTest { expectConfigValidation(SourceSink.SOURCE, connectorConfig); ClusterConfigState configState = new ClusterConfigState( - -1, - null, - Collections.singletonMap(CONNECTOR_NAME, 1), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), - Collections.singletonMap(new ConnectorTaskId(CONNECTOR_NAME, 0), taskConfig(SourceSink.SOURCE)), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - new HashSet<>(), - new HashSet<>(), - transformer); + -1, + null, + Collections.singletonMap(CONNECTOR_NAME, 1), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), + Collections.singletonMap(new ConnectorTaskId(CONNECTOR_NAME, 0), taskConfig(SourceSink.SOURCE)), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + new HashSet<>(), + new HashSet<>(), + transformer); when(worker.startSourceTask(taskId, configState, connectorConfig, taskConfig(SourceSink.SOURCE), herder, TargetState.STARTED)) - .thenReturn(false); + .thenReturn(false); herder.putConnectorConfig(CONNECTOR_NAME, connectorConfig, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -436,16 +444,13 @@ public class StandaloneHerderTest { FutureCallback cb = new FutureCallback<>(); herder.restartTask(taskId, cb); verify(worker).stopAndAwaitTask(taskId); - try { - cb.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); - fail("Expected restart callback to raise an exception"); - } catch (ExecutionException exception) { - assertEquals(ConnectException.class, exception.getCause().getClass()); - } + ExecutionException exception = assertThrows(ExecutionException.class, () -> cb.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); + assertEquals(ConnectException.class, exception.getCause().getClass()); } @Test public void testRestartConnectorAndTasksUnknownConnector() { + initialize(false); FutureCallback restartCallback = new FutureCallback<>(); RestartRequest restartRequest = new RestartRequest("UnknownConnector", false, true); herder.restartConnectorAndTasks(restartRequest, restartCallback); @@ -455,6 +460,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorAndTasksNoStatus() throws Exception { + initialize(true); RestartRequest restartRequest = new RestartRequest(CONNECTOR_NAME, false, true); doReturn(Optional.empty()).when(herder).buildRestartPlan(restartRequest); @@ -476,6 +482,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorAndTasksNoRestarts() throws Exception { + initialize(true); RestartRequest restartRequest = new RestartRequest(CONNECTOR_NAME, false, true); RestartPlan restartPlan = mock(RestartPlan.class); ConnectorStateInfo connectorStateInfo = mock(ConnectorStateInfo.class); @@ -500,6 +507,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorAndTasksOnlyConnector() throws Exception { + initialize(true); RestartRequest restartRequest = new RestartRequest(CONNECTOR_NAME, false, true); RestartPlan restartPlan = mock(RestartPlan.class); ConnectorStateInfo connectorStateInfo = mock(ConnectorStateInfo.class); @@ -508,7 +516,7 @@ public class StandaloneHerderTest { when(restartPlan.restartConnectorStateInfo()).thenReturn(connectorStateInfo); doReturn(Optional.of(restartPlan)).when(herder).buildRestartPlan(restartRequest); - expectAdd(SourceSink.SINK); + expectAdd(SourceSink.SINK, false); Map connectorConfig = connectorConfig(SourceSink.SINK); expectConfigValidation(SourceSink.SINK, connectorConfig); @@ -530,6 +538,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorAndTasksOnlyTasks() throws Exception { + initialize(true); ConnectorTaskId taskId = new ConnectorTaskId(CONNECTOR_NAME, 0); RestartRequest restartRequest = new RestartRequest(CONNECTOR_NAME, false, true); RestartPlan restartPlan = mock(RestartPlan.class); @@ -550,20 +559,20 @@ public class StandaloneHerderTest { doNothing().when(worker).stopAndAwaitTasks(Collections.singletonList(taskId)); ClusterConfigState configState = new ClusterConfigState( - -1, - null, - Collections.singletonMap(CONNECTOR_NAME, 1), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), - Collections.singletonMap(taskId, taskConfig(SourceSink.SINK)), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - new HashSet<>(), - new HashSet<>(), - transformer); + -1, + null, + Collections.singletonMap(CONNECTOR_NAME, 1), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), + Collections.singletonMap(taskId, taskConfig(SourceSink.SINK)), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + new HashSet<>(), + new HashSet<>(), + transformer); when(worker.startSinkTask(taskId, configState, connectorConfig, taskConfig(SourceSink.SINK), herder, TargetState.STARTED)) - .thenReturn(true); + .thenReturn(true); herder.putConnectorConfig(CONNECTOR_NAME, connectorConfig, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -580,6 +589,7 @@ public class StandaloneHerderTest { @Test public void testRestartConnectorAndTasksBoth() throws Exception { + initialize(true); ConnectorTaskId taskId = new ConnectorTaskId(CONNECTOR_NAME, 0); RestartRequest restartRequest = new RestartRequest(CONNECTOR_NAME, false, true); RestartPlan restartPlan = mock(RestartPlan.class); @@ -594,7 +604,7 @@ public class StandaloneHerderTest { ArgumentCaptor taskStatus = ArgumentCaptor.forClass(TaskStatus.class); - expectAdd(SourceSink.SINK); + expectAdd(SourceSink.SINK, false); Map connectorConfig = connectorConfig(SourceSink.SINK); expectConfigValidation(SourceSink.SINK, connectorConfig); @@ -605,20 +615,20 @@ public class StandaloneHerderTest { mockStartConnector(connectorConfig, null, TargetState.STARTED, null); ClusterConfigState configState = new ClusterConfigState( - -1, - null, - Collections.singletonMap(CONNECTOR_NAME, 1), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), - Collections.singletonMap(taskId, taskConfig(SourceSink.SINK)), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - new HashSet<>(), - new HashSet<>(), - transformer); + -1, + null, + Collections.singletonMap(CONNECTOR_NAME, 1), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), + Collections.singletonMap(taskId, taskConfig(SourceSink.SINK)), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + new HashSet<>(), + new HashSet<>(), + transformer); when(worker.startSinkTask(taskId, configState, connectorConfig, taskConfig(SourceSink.SINK), herder, TargetState.STARTED)) - .thenReturn(true); + .thenReturn(true); herder.putConnectorConfig(CONNECTOR_NAME, connectorConfig, false, createCallback); Herder.Created connectorInfo = createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -636,6 +646,7 @@ public class StandaloneHerderTest { @Test public void testCreateAndStop() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map connectorConfig = connectorConfig(SourceSink.SOURCE); @@ -657,6 +668,7 @@ public class StandaloneHerderTest { @Test public void testAccessors() throws Exception { + initialize(true); Map connConfig = connectorConfig(SourceSink.SOURCE); System.out.println(connConfig); @@ -680,14 +692,14 @@ public class StandaloneHerderTest { // Validate accessors with 1 connector doNothing().when(listConnectorsCb).onCompletion(null, singleton(CONNECTOR_NAME)); ConnectorInfo connInfo = new ConnectorInfo(CONNECTOR_NAME, connConfig, singletonList(new ConnectorTaskId(CONNECTOR_NAME, 0)), - ConnectorType.SOURCE); + ConnectorType.SOURCE); doNothing().when(connectorInfoCb).onCompletion(null, connInfo); TaskInfo taskInfo = new TaskInfo(new ConnectorTaskId(CONNECTOR_NAME, 0), taskConfig(SourceSink.SOURCE)); doNothing().when(taskConfigsCb).onCompletion(null, singletonList(taskInfo)); Map> tasksConfig = Collections.singletonMap(new ConnectorTaskId(CONNECTOR_NAME, 0), - taskConfig(SourceSink.SOURCE)); + taskConfig(SourceSink.SOURCE)); doNothing().when(tasksConfigCb).onCompletion(null, tasksConfig); // All operations are synchronous for StandaloneHerder, so we don't need to actually wait after making each call @@ -713,6 +725,7 @@ public class StandaloneHerderTest { @Test public void testPutConnectorConfig() throws Exception { + initialize(true); Map connConfig = connectorConfig(SourceSink.SOURCE); Map newConnConfig = new HashMap<>(connConfig); newConnConfig.put("foo", "bar"); @@ -720,7 +733,7 @@ public class StandaloneHerderTest { Callback> connectorConfigCb = mock(Callback.class); - expectAdd(SourceSink.SOURCE); + expectAdd(SourceSink.SOURCE, false); expectConfigValidation(SourceSink.SOURCE, connConfig, newConnConfig); // Should get first config @@ -733,12 +746,12 @@ public class StandaloneHerderTest { onStart.getValue().onCompletion(null, TargetState.STARTED); return true; }).when(worker).startConnector(eq(CONNECTOR_NAME), capturedConfig.capture(), any(), - eq(herder), eq(TargetState.STARTED), onStart.capture()); + eq(herder), eq(TargetState.STARTED), onStart.capture()); ConnectorTaskId taskId = new ConnectorTaskId(CONNECTOR_NAME, 0); // Generate same task config, but from different connector config, resulting // in task restarts when(worker.connectorTaskConfigs(CONNECTOR_NAME, new SourceConnectorConfig(plugins, newConnConfig, true))) - .thenReturn(singletonList(taskConfig(SourceSink.SOURCE))); + .thenReturn(singletonList(taskConfig(SourceSink.SOURCE))); doNothing().when(worker).stopAndAwaitTasks(Collections.singletonList(taskId)); doNothing().when(statusBackingStore).put(new TaskStatus(taskId, TaskStatus.State.DESTROYED, WORKER_ID, 0)); when(worker.startSourceTask(eq(taskId), any(), eq(newConnConfig), eq(taskConfig(SourceSink.SOURCE)), eq(herder), eq(TargetState.STARTED))).thenReturn(true); @@ -754,7 +767,7 @@ public class StandaloneHerderTest { herder.putConnectorConfig(CONNECTOR_NAME, newConnConfig, true, reconfigureCallback); Herder.Created newConnectorInfo = reconfigureCallback.get(1000L, TimeUnit.SECONDS); ConnectorInfo newConnInfo = new ConnectorInfo(CONNECTOR_NAME, newConnConfig, singletonList(new ConnectorTaskId(CONNECTOR_NAME, 0)), - ConnectorType.SOURCE); + ConnectorType.SOURCE); assertEquals(newConnInfo, newConnectorInfo.result()); assertEquals("bar", capturedConfig.getValue().get("foo")); @@ -764,6 +777,7 @@ public class StandaloneHerderTest { @Test public void testPatchConnectorConfigNotFound() { + initialize(false); Map connConfigPatch = new HashMap<>(); connConfigPatch.put("foo1", "baz1"); @@ -777,6 +791,7 @@ public class StandaloneHerderTest { @Test public void testPatchConnectorConfig() throws ExecutionException, InterruptedException, TimeoutException { + initialize(true); // Create the connector. Map originalConnConfig = connectorConfig(SourceSink.SOURCE); originalConnConfig.put("foo0", "unaffected"); @@ -794,15 +809,15 @@ public class StandaloneHerderTest { patchedConnConfig.remove("foo2"); patchedConnConfig.put("foo3", "added"); - expectAdd(SourceSink.SOURCE); + expectAdd(SourceSink.SOURCE, false, false, false); expectConfigValidation(SourceSink.SOURCE, originalConnConfig, patchedConnConfig); - expectConnectorStartingWithoutTasks(originalConnConfig, SourceSink.SOURCE); + expectConnectorStartingWithoutTasks(originalConnConfig, true); herder.putConnectorConfig(CONNECTOR_NAME, originalConnConfig, false, createCallback); createCallback.get(1000L, TimeUnit.SECONDS); - expectConnectorStartingWithoutTasks(patchedConnConfig, SourceSink.SOURCE); + expectConnectorStartingWithoutTasks(patchedConnConfig, false); FutureCallback> patchCallback = new FutureCallback<>(); herder.patchConnectorConfig(CONNECTOR_NAME, connConfigPatch, patchCallback); @@ -818,31 +833,33 @@ public class StandaloneHerderTest { assertEquals(patchedConnConfig, returnedConfig2); } - private void expectConnectorStartingWithoutTasks(Map config, SourceSink sourceSink) { - doNothing().when(worker).stopAndAwaitConnector(CONNECTOR_NAME); + private void expectConnectorStartingWithoutTasks(Map config, boolean mockStop) { + if (mockStop) { + doNothing().when(worker).stopAndAwaitConnector(CONNECTOR_NAME); + } final ArgumentCaptor> onStart = ArgumentCaptor.forClass(Callback.class); doAnswer(invocation -> { onStart.getValue().onCompletion(null, TargetState.STARTED); return true; }).when(worker).startConnector(eq(CONNECTOR_NAME), any(Map.class), any(), - eq(herder), eq(TargetState.STARTED), onStart.capture()); - ConnectorConfig connConfig = sourceSink == SourceSink.SOURCE ? - new SourceConnectorConfig(plugins, config, true) : - new SinkConnectorConfig(plugins, config); + eq(herder), eq(TargetState.STARTED), onStart.capture()); + ConnectorConfig connConfig = new SourceConnectorConfig(plugins, config, true); when(worker.connectorTaskConfigs(CONNECTOR_NAME, connConfig)) - .thenReturn(emptyList()); + .thenReturn(emptyList()); } @Test public void testPutTaskConfigs() { + initialize(false); Callback cb = mock(Callback.class); assertThrows(UnsupportedOperationException.class, () -> herder.putTaskConfigs(CONNECTOR_NAME, - singletonList(singletonMap("config", "value")), cb, null)); + singletonList(singletonMap("config", "value")), cb, null)); } @Test public void testCorruptConfig() { + initialize(false); Map config = new HashMap<>(); config.put(ConnectorConfig.NAME_CONFIG, CONNECTOR_NAME); config.put(ConnectorConfig.CONNECTOR_CLASS_CONFIG, BogusSinkConnector.class.getName()); @@ -852,9 +869,9 @@ public class StandaloneHerderTest { List errors = new ArrayList<>(singletonList(error)); String key = "foo.invalid.key"; when(connectorMock.validate(config)).thenReturn( - new Config( - singletonList(new ConfigValue(key, null, Collections.emptyList(), errors)) - ) + new Config( + singletonList(new ConfigValue(key, null, Collections.emptyList(), errors)) + ) ); ConfigDef configDef = new ConfigDef(); configDef.define(key, ConfigDef.Type.STRING, ConfigDef.Importance.HIGH, ""); @@ -869,24 +886,25 @@ public class StandaloneHerderTest { herder.putConnectorConfig(CONNECTOR_NAME, config, true, createCallback); ExecutionException e = assertThrows( - "Should have failed to configure connector", - ExecutionException.class, - () -> createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS) + ExecutionException.class, + () -> createCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS), + "Should have failed to configure connector" ); assertNotNull(e.getCause()); Throwable cause = e.getCause(); assertInstanceOf(BadRequestException.class, cause); assertEquals( - cause.getMessage(), - "Connector configuration is invalid and contains the following 1 error(s):\n" + - error + "\n" + - "You can also find the above list of errors at the endpoint `/connector-plugins/{connectorType}/config/validate`" + cause.getMessage(), + "Connector configuration is invalid and contains the following 1 error(s):\n" + + error + "\n" + + "You can also find the above list of errors at the endpoint `/connector-plugins/{connectorType}/config/validate`" ); verify(loaderSwap).close(); } @Test public void testTargetStates() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); Map connectorConfig = connectorConfig(SourceSink.SOURCE); @@ -922,10 +940,11 @@ public class StandaloneHerderTest { @Test public void testModifyConnectorOffsetsUnknownConnector() { + initialize(false); FutureCallback alterOffsetsCallback = new FutureCallback<>(); herder.alterConnectorOffsets("unknown-connector", - Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), - alterOffsetsCallback); + Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), + alterOffsetsCallback); ExecutionException e = assertThrows(ExecutionException.class, () -> alterOffsetsCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); assertInstanceOf(NotFoundException.class, e.getCause()); @@ -937,26 +956,27 @@ public class StandaloneHerderTest { @Test public void testModifyConnectorOffsetsConnectorNotInStoppedState() { + initialize(false); Map connectorConfig = connectorConfig(SourceSink.SOURCE); herder.configState = new ClusterConfigState( - 10, - null, - Collections.singletonMap(CONNECTOR_NAME, 3), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), - Collections.singletonMap(CONNECTOR_NAME, TargetState.PAUSED), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - Collections.emptySet(), - Collections.emptySet() + 10, + null, + Collections.singletonMap(CONNECTOR_NAME, 3), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), + Collections.singletonMap(CONNECTOR_NAME, TargetState.PAUSED), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + Collections.emptySet(), + Collections.emptySet() ); FutureCallback alterOffsetsCallback = new FutureCallback<>(); herder.alterConnectorOffsets(CONNECTOR_NAME, - Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), - alterOffsetsCallback); + Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), + alterOffsetsCallback); ExecutionException e = assertThrows(ExecutionException.class, () -> alterOffsetsCallback.get(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); assertInstanceOf(BadRequestException.class, e.getCause()); @@ -968,6 +988,7 @@ public class StandaloneHerderTest { @Test public void testAlterConnectorOffsets() throws Exception { + initialize(false); ArgumentCaptor> workerCallbackCapture = ArgumentCaptor.forClass(Callback.class); Message msg = new Message("The offsets for this connector have been altered successfully"); doAnswer(invocation -> { @@ -978,27 +999,28 @@ public class StandaloneHerderTest { Map connectorConfig = connectorConfig(SourceSink.SOURCE); herder.configState = new ClusterConfigState( - 10, - null, - Collections.singletonMap(CONNECTOR_NAME, 0), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STOPPED), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - Collections.emptySet(), - Collections.emptySet() + 10, + null, + Collections.singletonMap(CONNECTOR_NAME, 0), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STOPPED), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + Collections.emptySet(), + Collections.emptySet() ); FutureCallback alterOffsetsCallback = new FutureCallback<>(); herder.alterConnectorOffsets(CONNECTOR_NAME, - Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), - alterOffsetsCallback); + Collections.singletonMap(Collections.singletonMap("partitionKey", "partitionValue"), Collections.singletonMap("offsetKey", "offsetValue")), + alterOffsetsCallback); assertEquals(msg, alterOffsetsCallback.get(1000, TimeUnit.MILLISECONDS)); } @Test public void testResetConnectorOffsets() throws Exception { + initialize(false); ArgumentCaptor> workerCallbackCapture = ArgumentCaptor.forClass(Callback.class); Message msg = new Message("The offsets for this connector have been reset successfully"); @@ -1010,25 +1032,26 @@ public class StandaloneHerderTest { Map connectorConfig = connectorConfig(SourceSink.SOURCE); herder.configState = new ClusterConfigState( - 10, - null, - Collections.singletonMap(CONNECTOR_NAME, 0), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STOPPED), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - Collections.emptySet(), - Collections.emptySet() + 10, + null, + Collections.singletonMap(CONNECTOR_NAME, 0), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig(SourceSink.SOURCE)), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STOPPED), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + Collections.emptySet(), + Collections.emptySet() ); FutureCallback resetOffsetsCallback = new FutureCallback<>(); herder.resetConnectorOffsets(CONNECTOR_NAME, resetOffsetsCallback); assertEquals(msg, resetOffsetsCallback.get(1000, TimeUnit.MILLISECONDS)); } - @Test() + @Test public void testRequestTaskReconfigurationDoesNotDeadlock() throws Exception { + initialize(true); expectAdd(SourceSink.SOURCE); // Start the connector @@ -1056,9 +1079,9 @@ public class StandaloneHerderTest { Map updatedTaskConfig2 = taskConfig(SourceSink.SOURCE); updatedTaskConfig2.put("dummy-task-property", "2"); when(worker.connectorTaskConfigs(eq(CONNECTOR_NAME), any())) - .thenReturn( - Collections.singletonList(updatedTaskConfig1), - Collections.singletonList(updatedTaskConfig2)); + .thenReturn( + Collections.singletonList(updatedTaskConfig1), + Collections.singletonList(updatedTaskConfig2)); // Set new config on the connector and tasks FutureCallback> reconfigureCallback = new FutureCallback<>(); @@ -1076,12 +1099,25 @@ public class StandaloneHerderTest { } private void expectAdd(SourceSink sourceSink) { + expectAdd(sourceSink, true); + } + private void expectAdd(SourceSink sourceSink, boolean mockStartConnector) { + expectAdd(sourceSink, mockStartConnector, true, true); + } + + private void expectAdd(SourceSink sourceSink, + boolean mockStartConnector, + boolean mockConnectorTaskConfigs, + boolean mockStartSourceTask) { Map connectorProps = connectorConfig(sourceSink); ConnectorConfig connConfig = sourceSink == SourceSink.SOURCE ? - new SourceConnectorConfig(plugins, connectorProps, true) : - new SinkConnectorConfig(plugins, connectorProps); + new SourceConnectorConfig(plugins, connectorProps, true) : + new SinkConnectorConfig(plugins, connectorProps); + + if (mockStartConnector) { + mockStartConnector(connectorProps, TargetState.STARTED, TargetState.STARTED, null); + } - mockStartConnector(connectorProps, TargetState.STARTED, TargetState.STARTED, null); when(worker.isRunning(CONNECTOR_NAME)).thenReturn(true); if (sourceSink == SourceSink.SOURCE) { when(worker.isTopicCreationEnabled()).thenReturn(true); @@ -1092,25 +1128,29 @@ public class StandaloneHerderTest { Map connectorConfig = connectorConfig(sourceSink); Map generatedTaskProps = taskConfig(sourceSink); - when(worker.connectorTaskConfigs(CONNECTOR_NAME, connConfig)) - .thenReturn(singletonList(generatedTaskProps)); + if (mockConnectorTaskConfigs) { + when(worker.connectorTaskConfigs(CONNECTOR_NAME, connConfig)).thenReturn(singletonList(generatedTaskProps)); + } ClusterConfigState configState = new ClusterConfigState( - -1, - null, - Collections.singletonMap(CONNECTOR_NAME, 1), - Collections.singletonMap(CONNECTOR_NAME, connectorConfig), - Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), - Collections.singletonMap(new ConnectorTaskId(CONNECTOR_NAME, 0), generatedTaskProps), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), - new HashSet<>(), - new HashSet<>(), - transformer); - if (sourceSink.equals(SourceSink.SOURCE)) { + -1, + null, + Collections.singletonMap(CONNECTOR_NAME, 1), + Collections.singletonMap(CONNECTOR_NAME, connectorConfig), + Collections.singletonMap(CONNECTOR_NAME, TargetState.STARTED), + Collections.singletonMap(new ConnectorTaskId(CONNECTOR_NAME, 0), generatedTaskProps), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.singletonMap(CONNECTOR_NAME, new AppliedConnectorConfig(connectorConfig)), + new HashSet<>(), + new HashSet<>(), + transformer); + + if (sourceSink.equals(SourceSink.SOURCE) && mockStartSourceTask) { when(worker.startSourceTask(new ConnectorTaskId(CONNECTOR_NAME, 0), configState, connectorConfig(sourceSink), generatedTaskProps, herder, TargetState.STARTED)).thenReturn(true); - } else { + } + + if (sourceSink.equals(SourceSink.SINK)) { when(worker.startSinkTask(new ConnectorTaskId(CONNECTOR_NAME, 0), configState, connectorConfig(sourceSink), generatedTaskProps, herder, TargetState.STARTED)).thenReturn(true); } @@ -1126,7 +1166,7 @@ public class StandaloneHerderTest { }); when(worker.isSinkConnector(CONNECTOR_NAME)) - .thenReturn(sourceSink == SourceSink.SINK); + .thenReturn(sourceSink == SourceSink.SINK); } private void expectTargetState(String connector, TargetState state) { @@ -1140,8 +1180,8 @@ public class StandaloneHerderTest { private ConnectorInfo createdInfo(SourceSink sourceSink) { return new ConnectorInfo(CONNECTOR_NAME, connectorConfig(sourceSink), - singletonList(new ConnectorTaskId(CONNECTOR_NAME, 0)), - SourceSink.SOURCE == sourceSink ? ConnectorType.SOURCE : ConnectorType.SINK); + singletonList(new ConnectorTaskId(CONNECTOR_NAME, 0)), + SourceSink.SOURCE == sourceSink ? ConnectorType.SOURCE : ConnectorType.SINK); } private void expectStop() { @@ -1181,8 +1221,8 @@ public class StandaloneHerderTest { } private void expectConfigValidation( - SourceSink sourceSink, - Map... configs + SourceSink sourceSink, + Map... configs ) { // config validation Connector connectorMock = sourceSink == SourceSink.SOURCE ? mock(SourceConnector.class) : mock(SinkConnector.class);