blob: b75c7e3927c0accde4080eb77ce0969ebf59dc88 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal;
import static org.apache.geode.distributed.internal.DistributionConfig.DEFAULT_MEMBERSHIP_PORT_RANGE;
import static org.apache.geode.internal.AvailablePort.AVAILABLE_PORTS_LOWER_BOUND;
import static org.apache.geode.internal.AvailablePort.AVAILABLE_PORTS_UPPER_BOUND;
import static org.apache.geode.internal.AvailablePort.MULTICAST;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPortRange;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPortRangeKeepers;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableUDPPort;
import static org.apache.geode.internal.AvailablePortHelper.initializeUniquePortRange;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeFalse;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.apache.geode.internal.AvailablePort.Keeper;
import org.apache.geode.internal.lang.SystemUtils;
@RunWith(JUnitParamsRunner.class)
public class AvailablePortHelperIntegrationTest {
private Set<ServerSocket> serverSockets;
@Before
public void before() throws Exception {
this.serverSockets = new HashSet<>();
}
@After
public void after() throws Exception {
for (ServerSocket serverSocket : this.serverSockets) {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
} catch (IOException ignore) {
System.err.println("Unable to close " + serverSocket);
}
}
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_zero(final boolean useMembershipPortRange)
throws Exception {
int[] results = getRandomAvailableTCPPortRange(0, useMembershipPortRange);
assertThat(results).isEmpty();
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_one_returnsOne(final boolean useMembershipPortRange)
throws Exception {
int[] results = getRandomAvailableTCPPortRange(1, useMembershipPortRange);
assertThat(results).hasSize(1);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_two_returnsTwo(final boolean useMembershipPortRange)
throws Exception {
int[] results = getRandomAvailableTCPPortRange(2, useMembershipPortRange);
assertThat(results).hasSize(2);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_many_returnsMany(final boolean useMembershipPortRange)
throws Exception {
int[] results = getRandomAvailableTCPPortRange(10, useMembershipPortRange);
assertThat(results).hasSize(10);
assertPortsAreUsable(results);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_returnsUniquePorts(
final boolean useMembershipPortRange) throws Exception {
int[] results = getRandomAvailableTCPPortRange(10, useMembershipPortRange);
Set<Integer> ports = new HashSet<>();
for (int port : results) {
ports.add(port);
}
assertThat(ports).hasSize(results.length);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_returnsConsecutivePorts(
final boolean useMembershipPortRange) throws Exception {
int[] results = getRandomAvailableTCPPortRange(10, useMembershipPortRange);
List<Integer> ports = new ArrayList<>();
for (int port : results) {
if (useMembershipPortRange) {
assertThat(port).isGreaterThanOrEqualTo(DEFAULT_MEMBERSHIP_PORT_RANGE[0])
.isLessThanOrEqualTo(DEFAULT_MEMBERSHIP_PORT_RANGE[1]);
} else {
assertThat(port).isGreaterThanOrEqualTo(AVAILABLE_PORTS_LOWER_BOUND)
.isLessThanOrEqualTo(AVAILABLE_PORTS_UPPER_BOUND);
}
ports.add(port);
}
assertThat(ports).hasSize(10);
int previousPort = 0;
for (int port : ports) {
if (previousPort != 0) {
assertThat(port).isEqualTo(previousPort + 1);
}
previousPort = port;
}
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_zero(final boolean useMembershipPortRange)
throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(0, useMembershipPortRange);
assertThat(results).isEmpty();
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_one_returnsOne(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(1, useMembershipPortRange);
assertThat(results).hasSize(1);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_two_returnsTwo(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(2, useMembershipPortRange);
assertThat(results).hasSize(2);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_many_returnsMany(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(10, useMembershipPortRange);
assertThat(results).hasSize(10);
assertKeepersAreUsable(results);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_returnsUsableKeeper(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(1, useMembershipPortRange);
assertKeepersAreUsable(results);
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_returnsUniqueKeepers(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(10, useMembershipPortRange);
Set<Integer> ports = new HashSet<>();
for (Keeper keeper : results) {
ports.add(keeper.getPort());
}
assertThat(ports).hasSize(results.size());
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRangeKeepers_returnsConsecutivePorts(
final boolean useMembershipPortRange) throws Exception {
List<Keeper> results = getRandomAvailableTCPPortRangeKeepers(10, useMembershipPortRange);
List<Integer> ports = new ArrayList<>();
for (Keeper keeper : results) {
assertThat(keeper).isNotNull();
int port = keeper.getPort();
if (useMembershipPortRange) {
assertThat(port).isGreaterThanOrEqualTo(DEFAULT_MEMBERSHIP_PORT_RANGE[0])
.isLessThanOrEqualTo(DEFAULT_MEMBERSHIP_PORT_RANGE[1]);
} else {
assertThat(port).isGreaterThanOrEqualTo(AVAILABLE_PORTS_LOWER_BOUND)
.isLessThanOrEqualTo(AVAILABLE_PORTS_UPPER_BOUND);
}
ports.add(port);
}
assertThat(ports).hasSize(10);
int previousPort = 0;
for (int port : ports) {
if (previousPort != 0) {
assertThat(port).isEqualTo(previousPort + 1);
}
previousPort = port;
}
}
@Test
public void getRandomAvailableUDPPort_succeeds() throws IOException {
int udpPort = getRandomAvailableUDPPort();
assertThat(udpPort).isNotZero();
assertThat(AvailablePort.isPortAvailable(udpPort, MULTICAST)).isTrue();
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPortRange_returnsUniqueRanges(
final boolean useMembershipPortRange) {
Set<Integer> ports = new HashSet<>();
for (int i = 0; i < 1000; ++i) {
int[] testPorts = getRandomAvailableTCPPortRange(5, useMembershipPortRange);
for (int testPort : testPorts) {
assertThat(ports).doesNotContain(testPort);
ports.add(testPort);
}
}
}
@Test
@Parameters({"true", "false"})
public void getRandomAvailableTCPPort_returnsUniqueValues(final boolean useMembershipPortRange) {
Set<Integer> ports = new HashSet<>();
for (int i = 0; i < 1000; ++i) {
int testPort = getRandomAvailableTCPPorts(1, useMembershipPortRange)[0];
assertThat(ports).doesNotContain(testPort);
ports.add(testPort);
}
}
@Test
@Parameters({"true", "false"})
public void initializeUniquePortRange_willReturnSamePortsForSameRange(
final boolean useMembershipPortRange) {
assumeFalse(
"Windows has ports scattered throughout the range that makes this test difficult to pass consistently",
SystemUtils.isWindows());
for (int i = 0; i < 100; ++i) {
initializeUniquePortRange(i);
int[] testPorts = getRandomAvailableTCPPorts(3, useMembershipPortRange);
initializeUniquePortRange(i);
assertThat(getRandomAvailableTCPPorts(3, useMembershipPortRange)).isEqualTo(testPorts);
}
}
@Test
@Parameters({"true", "false"})
public void initializeUniquePortRange_willReturnUniquePortsForUniqueRanges(
final boolean useMembershipPortRange) {
assumeFalse(
"Windows has ports scattered throughout the range that makes this test difficult to pass consistently",
SystemUtils.isWindows());
Set<Integer> ports = new HashSet<>();
for (int i = 0; i < 100; ++i) {
initializeUniquePortRange(i);
int[] testPorts = getRandomAvailableTCPPorts(5, useMembershipPortRange);
for (int testPort : testPorts) {
assertThat(ports).doesNotContain(testPort);
ports.add(testPort);
}
}
}
private void assertPortsAreUsable(int[] ports) throws IOException {
for (int port : ports) {
assertPortIsUsable(port);
}
}
private void assertPortIsUsable(int port) throws IOException {
ServerSocket serverSocket = createServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(port));
assertThat(serverSocket.isBound()).isTrue();
assertThat(serverSocket.isClosed()).isFalse();
serverSocket.close();
assertThat(serverSocket.isClosed()).isTrue();
}
private void assertKeepersAreUsable(Collection<Keeper> keepers) throws IOException {
for (Keeper keeper : keepers) {
assertKeeperIsUsable(keeper);
}
}
private void assertKeeperIsUsable(Keeper keeper) throws IOException {
int port = keeper.getPort();
keeper.release();
assertPortIsUsable(port);
}
private ServerSocket createServerSocket() throws IOException {
ServerSocket serverSocket = new ServerSocket();
this.serverSockets.add(serverSocket);
return serverSocket;
}
}