package org.arquillian.cube.openshift.test.portfowarder; import java.net.Inet4Address; import java.net.ServerSocket; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.Assert; import org.junit.Test; public class PortForwarderTest { private final String[] portsToForwardStringBackward = {"test:1234", "test:9999", "test:9990", "test:8080"}; private final String[] portsToForwardString = {"test:0:1234", "test:0:9999", "test:0:9990", "test:0:8080"}; private final String[] useSamePortsToForwardString = {"test::1234", "test::9999", "test::9990", "test::8080"}; private Set<String> portsToForward = new HashSet<String>(); private Map<Integer, Integer> proxiedPorts = new HashMap<>(); @Test public void testAlleatoryPortBackwar() { resolvePorts("aleatoryPortBackward"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertNotEquals(entry.getKey(), entry.getValue()); } } @Test public void testAlleatoryPort() { resolvePorts("aleatoryPort"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertNotEquals(entry.getKey(), entry.getValue()); } } @Test public void testSamePort() { resolvePorts("samePort"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertEquals(entry.getKey(), entry.getValue()); } } @Test public void testSameAndAleatoryPort() { //Test1 pod:port portsToForward.add("test:8080"); resolvePorts("none"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertNotEquals(entry.getKey(), entry.getValue()); } //Test2 pod::port portsToForward.add("test::8180"); resolvePorts("none"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertEquals(entry.getKey(), entry.getValue()); } //Test3 pod:0:port portsToForward.add("test:0:8280"); resolvePorts("none"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertNotEquals(entry.getKey(), entry.getValue()); } //Test4 pod:port:port portsToForward.add("test:8380:8380"); resolvePorts("none"); for (Map.Entry<Integer, Integer> entry : proxiedPorts.entrySet()) { //key = containerPort, value = mappedPort Assert.assertEquals(entry.getKey(), entry.getValue()); } } @Test(expected = IllegalStateException.class) public void testNegativePort() { //test should fail, let's try to map a invalid port Assert.assertEquals(-1, allocateLocalPort(-1)); } private void resolvePorts(String method) { //cleaning previous ports portsToForward = new HashSet<String>(); if ("aleatoryPortBackward".equals(method)) { for (int i = 0; i < portsToForwardStringBackward.length; i++) { portsToForward.add(portsToForwardStringBackward[i]); } } else if ("aleatoryPort".equals(method)) { for (int i = 0; i < portsToForwardString.length; i++) { portsToForward.add(portsToForwardString[i]); } } else if ("samePort".equals(method)) { for (int i = 0; i < useSamePortsToForwardString.length; i++) { portsToForward.add(useSamePortsToForwardString[i]); } } // Syntax: pod:port - backward compatibility // pod::port - use the same port than container port // pod:0:port - use an aleatory port for (String proxy : portsToForward) { String[] split = proxy.split(":"); if (split.length == 2 || split.length == 3) { final int containerPort = !"".equals(split[1]) ? Integer.valueOf(split[1]) : Integer.valueOf(split[2]); int mappedPort = 0; if (split.length == 3 && "".equals(split[1])) { // pod::port - use the same port than container port mappedPort = allocateLocalPort(Integer.valueOf(split[2])); } else if (split.length == 3 && "0".equals(split[1])) { //pod:0:port - use an aleatory port or pod:port:port to map the same port mappedPort = allocateLocalPort(Integer.valueOf(split[1])); } else { // pod:port - backward compatibility, aleatory port mappedPort = allocateLocalPort(0); } proxiedPorts.put(containerPort, mappedPort); } } } //the original method is inside a private inner class, so I am replicating it here. private int allocateLocalPort(int port) { try { try (ServerSocket serverSocket = new ServerSocket(port, 0, Inet4Address.getLocalHost())) { return serverSocket.getLocalPort(); } } catch (Throwable t) { throw new IllegalStateException("Could not allocate local port for forwarding proxy", t); } } }