mirror of https://github.com/apache/kafka.git
KAFKA-18546: Use mocks instead of a real DNS lookup to the outside (#18565)
Since the example.com DNS lookup changed the second time within one year, we rewrote the unit tests for ClientUtils so that they do not make a real DNS lookup to the outside but use mocks. Reviewers: PoAn Yang <payang@apache.org>, Chia-Ping Tsai <chia7712@gmail.com>, Lianet Magrans <lmagrans@confluent.io>
This commit is contained in:
parent
4038edfafe
commit
e7a7efd602
|
@ -19,24 +19,27 @@ package org.apache.kafka.clients;
|
|||
import org.apache.kafka.common.config.ConfigException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
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.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockConstruction;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class ClientUtilsTest {
|
||||
|
||||
private final HostResolver hostResolver = new DefaultHostResolver();
|
||||
|
||||
@Test
|
||||
public void testParseAndValidateAddresses() {
|
||||
checkWithoutLookup("127.0.0.1:8000");
|
||||
|
@ -57,28 +60,39 @@ public class ClientUtilsTest {
|
|||
checkWithoutLookup("[::1]:8000");
|
||||
checkWithoutLookup("[2001:db8:85a3:8d3:1319:8a2e:370:7348]:1234", "localhost:10000");
|
||||
|
||||
// With lookup of example.com, either one or two addresses are expected depending on
|
||||
// whether ipv4 and ipv6 are enabled
|
||||
List<InetSocketAddress> validatedAddresses = checkWithLookup(Collections.singletonList("example.com:10000"));
|
||||
assertFalse(validatedAddresses.isEmpty(), "Unexpected addresses " + validatedAddresses);
|
||||
List<String> validatedHostNames = validatedAddresses.stream().map(InetSocketAddress::getHostName)
|
||||
.collect(Collectors.toList());
|
||||
List<String> expectedHostNames = asList(
|
||||
"a23-215-0-136.deploy.static.akamaitechnologies.com",
|
||||
"a23-192-228-84.deploy.static.akamaitechnologies.com",
|
||||
"a23-215-0-138.deploy.static.akamaitechnologies.com",
|
||||
"a96-7-128-175.deploy.static.akamaitechnologies.com",
|
||||
"a23-192-228-80.deploy.static.akamaitechnologies.com",
|
||||
"a96-7-128-198.deploy.static.akamaitechnologies.com",
|
||||
"2600:1406:3a00:21:0:0:173e:2e66",
|
||||
"2600:1408:ec00:36:0:0:1736:7f31",
|
||||
"2600:1406:3a00:21:0:0:173e:2e65",
|
||||
"2600:1408:ec00:36:0:0:1736:7f24",
|
||||
"2600:1406:bc00:53:0:0:b81e:94ce",
|
||||
"2600:1406:bc00:53:0:0:b81e:94c8"
|
||||
);
|
||||
assertTrue(expectedHostNames.containsAll(validatedHostNames), "Unexpected addresses " + validatedHostNames);
|
||||
validatedAddresses.forEach(address -> assertEquals(10000, address.getPort()));
|
||||
String hostname = "example.com";
|
||||
Integer port = 10000;
|
||||
String canonicalHostname1 = "canonical_hostname1";
|
||||
String canonicalHostname2 = "canonical_hostname2";
|
||||
try (final MockedStatic<InetAddress> inetAddress = mockStatic(InetAddress.class)) {
|
||||
InetAddress inetAddress1 = mock(InetAddress.class);
|
||||
when(inetAddress1.getCanonicalHostName()).thenReturn(canonicalHostname1);
|
||||
InetAddress inetAddress2 = mock(InetAddress.class);
|
||||
when(inetAddress2.getCanonicalHostName()).thenReturn(canonicalHostname2);
|
||||
inetAddress.when(() -> InetAddress.getAllByName(hostname))
|
||||
.thenReturn(new InetAddress[]{inetAddress1, inetAddress2});
|
||||
try (MockedConstruction<InetSocketAddress> inetSocketAddress =
|
||||
mockConstruction(
|
||||
InetSocketAddress.class,
|
||||
(mock, context) -> {
|
||||
when(mock.isUnresolved()).thenReturn(false);
|
||||
when(mock.getHostName()).thenReturn((String) context.arguments().get(0));
|
||||
when(mock.getPort()).thenReturn((Integer) context.arguments().get(1));
|
||||
})
|
||||
) {
|
||||
List<InetSocketAddress> validatedAddresses = checkWithLookup(Collections.singletonList(hostname + ":" + port));
|
||||
assertEquals(2, inetSocketAddress.constructed().size());
|
||||
assertEquals(2, validatedAddresses.size());
|
||||
assertTrue(validatedAddresses.containsAll(List.of(
|
||||
inetSocketAddress.constructed().get(0),
|
||||
inetSocketAddress.constructed().get(1)))
|
||||
);
|
||||
validatedAddresses.forEach(address -> assertEquals(port, address.getPort()));
|
||||
validatedAddresses.stream().map(InetSocketAddress::getHostName).forEach(
|
||||
hostName -> assertTrue(List.of(canonicalHostname1, canonicalHostname2).contains(hostName))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -99,7 +113,21 @@ public class ClientUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testOnlyBadHostname() {
|
||||
assertThrows(ConfigException.class, () -> checkWithoutLookup("some.invalid.hostname.foo.bar.local:9999"));
|
||||
try (MockedConstruction<InetSocketAddress> inetSocketAddress =
|
||||
mockConstruction(
|
||||
InetSocketAddress.class,
|
||||
(mock, context) -> when(mock.isUnresolved()).thenReturn(true)
|
||||
)
|
||||
) {
|
||||
Exception exception = assertThrows(
|
||||
ConfigException.class,
|
||||
() -> checkWithoutLookup("some.invalid.hostname.foo.bar.local:9999")
|
||||
);
|
||||
assertEquals(
|
||||
"No resolvable bootstrap urls given in " + CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
|
||||
exception.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -122,8 +150,13 @@ public class ClientUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testResolveUnknownHostException() {
|
||||
assertThrows(UnknownHostException.class,
|
||||
() -> ClientUtils.resolve("some.invalid.hostname.foo.bar.local", hostResolver));
|
||||
HostResolver throwingHostResolver = host -> {
|
||||
throw new UnknownHostException();
|
||||
};
|
||||
assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> ClientUtils.resolve("some.invalid.hostname.foo.bar.local", throwingHostResolver)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,5 +175,4 @@ public class ClientUtilsTest {
|
|||
private List<InetSocketAddress> checkWithLookup(List<String> url) {
|
||||
return ClientUtils.parseAndValidateAddresses(url, ClientDnsLookup.RESOLVE_CANONICAL_BOOTSTRAP_SERVERS_ONLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue