blob: 94f5fa6bb83daacd39e2e1726d848549f5b5fcae [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.knox.gateway;
import org.apache.knox.gateway.config.GatewayConfig;
import org.easymock.EasyMock;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
/**
* Test the Gateway Topology Port Mapping config
*
*/
public class GatewayPortMappingConfigTest {
/**
* Mock gateway config
*/
private static GatewayConfig gatewayConfig;
private static int eeriePort;
private static int ontarioPort;
private static int huronPort;
private static int defaultPort;
private static Server gatewayServer;
@Rule
public ExpectedException exception = ExpectedException.none();
public GatewayPortMappingConfigTest() {
super();
}
@BeforeClass
public static void init() throws Exception {
Map<String, Integer> topologyPortMapping = new ConcurrentHashMap<>();
// get unique ports
eeriePort = getAvailablePort(1240, 49151);
ontarioPort = getAvailablePort(eeriePort + 1, 49151);
huronPort = getAvailablePort(ontarioPort + 1, 49151);
defaultPort = getAvailablePort(huronPort + 1, 49151);
topologyPortMapping.put("eerie", eeriePort);
topologyPortMapping.put("ontario", ontarioPort);
topologyPortMapping.put("huron", huronPort);
gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class);
EasyMock.expect(gatewayConfig.getGatewayPortMappings())
.andReturn(topologyPortMapping).anyTimes();
EasyMock.expect(gatewayConfig.getGatewayPort()).andReturn(defaultPort)
.anyTimes();
EasyMock.replay(gatewayConfig);
// Start gateway to check port conflicts
startGatewayServer();
}
@AfterClass
public static void stopServers() {
try {
gatewayServer.stop();
} catch (final Exception e) {
e.printStackTrace(System.err);
}
}
/**
* This utility method will return the next available port
* that can be used.
* @param min min port to check
* @param max max port to check
* @return Port that is available.
*/
private static int getAvailablePort(final int min, final int max) {
for (int i = min; i <= max; i++) {
if (!GatewayServer.isPortInUse(i)) {
return i;
}
}
// too bad
return -1;
}
/*
* This method simply tests the configs
*/
@Test
public void testGatewayConfig() {
assertThat(gatewayConfig.getGatewayPortMappings().get("eerie"),
greaterThan(-1));
assertThat(gatewayConfig.getGatewayPortMappings().get("ontario"),
greaterThan(-1));
assertThat(gatewayConfig.getGatewayPortMappings().get("huron"),
greaterThan(-1));
}
/*
* Test case where topologies "eerie" and "huron" use same ports.
*/
@Test
public void testCheckPortConflict()
throws IOException, NoSuchFieldException, IllegalAccessException {
/* Check port conflict with default port */
exception.expect(IOException.class);
exception.expectMessage(String.format(Locale.ROOT,
" Port %d used by topology %s is used by other topology, ports for topologies (if defined) have to be unique. ",
huronPort, "eerie"));
GatewayServer gatewayServer = new GatewayServer(gatewayConfig);
Server mockedJetty = EasyMock.createNiceMock(Server.class);
ServerConnector mockConnector = EasyMock.createNiceMock(ServerConnector.class);
EasyMock.expect(mockConnector.getPort()).andReturn(huronPort).anyTimes();
EasyMock.replay(mockConnector);
ServerConnector[] mockConnectorArray = new ServerConnector[] {mockConnector};
EasyMock.expect(mockedJetty.getConnectors()).andReturn(mockConnectorArray).anyTimes();
EasyMock.replay(mockedJetty);
Field field = gatewayServer.getClass().getDeclaredField("jetty");
field.setAccessible(true);
field.set(gatewayServer, mockedJetty);
gatewayServer.checkPortConflict(huronPort, "eerie", gatewayConfig);
}
/*
* Test a case where gateway is already running and same port is used to start
* another gateway.
*/
@Test
public void testDefaultPortInUse() throws IOException {
exception.expect(IOException.class);
exception
.expectMessage(String.format(Locale.ROOT, "Port %d already in use.", defaultPort));
final GatewayServer gatewayServer = new GatewayServer(gatewayConfig);
gatewayServer.checkPortConflict(defaultPort, null, gatewayConfig);
}
private static void startGatewayServer() throws Exception {
// use default Max threads
gatewayServer = new Server(defaultPort);
final ServerConnector connector = new ServerConnector(gatewayServer);
gatewayServer.addConnector(connector);
// workaround so we can add our handler later at runtime
HandlerCollection handlers = new HandlerCollection(true);
// add some initial handlers
ContextHandler context = new ContextHandler();
context.setContextPath("/");
handlers.addHandler(context);
gatewayServer.setHandler(handlers);
// Start Server
gatewayServer.start();
}
}