/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed 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 com.linkedin.pinot.common.http; import com.google.common.base.Throwables; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.methods.GetMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class MultiGetRequestTest { private static final Logger LOGGER = LoggerFactory.getLogger(MultiGetRequest.class); List<HttpServer> servers = new ArrayList<>(); final int portStart = 14000; final String SUCCESS_MSG = "success"; final String ERROR_MSG = "error"; final String TIMEOUT_MSG = "Timeout"; final int SUCCESS_CODE = 200; final int ERROR_CODE = 500; final String URI_PATH = "/foo"; final int TIMEOUT_MS = 5000; @BeforeTest public void setUpTest() throws IOException { startServer(portStart, createHandler(SUCCESS_CODE, SUCCESS_MSG, 0)); startServer(portStart + 1, createHandler(ERROR_CODE, ERROR_MSG, 0)); startServer(portStart + 2, createHandler(SUCCESS_CODE, TIMEOUT_MSG, TIMEOUT_MS)); } @AfterTest public void tearDownTest() { for (HttpServer server : servers) { server.stop(0); } } private HttpHandler createHandler(final int status, final String msg, final int sleepTimeMs) { return new HttpHandler() { @Override public void handle(HttpExchange httpExchange) throws IOException { if (sleepTimeMs > 0) { try { Thread.sleep(sleepTimeMs); } catch (InterruptedException e) { LOGGER.info("Handler interrupted during sleep"); } } httpExchange.sendResponseHeaders(status, msg.length()); OutputStream responseBody = httpExchange.getResponseBody(); responseBody.write(msg.getBytes()); responseBody.close(); } }; } private HttpServer startServer(int port, HttpHandler handler) throws IOException { final HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(URI_PATH, handler); new Thread(new Runnable() { @Override public void run() { server.start(); } }).start(); servers.add(server); return server; } @Test public void testMultiGet() { MultiGetRequest mget = new MultiGetRequest(Executors.newCachedThreadPool(), new MultiThreadedHttpConnectionManager()); List<String> urls = Arrays.asList("http://localhost:" + String.valueOf(portStart) + URI_PATH, "http://localhost:" + String.valueOf(portStart + 1) + URI_PATH, "http://localhost:" + String.valueOf(portStart + 2) + URI_PATH, // 2nd request to the same server "http://localhost:" + String.valueOf(portStart) + URI_PATH ); // timeout value needs to be less than 5000ms set above for // third server final int requestTimeoutMs = 1000; CompletionService<GetMethod> completionService = mget.execute(urls, requestTimeoutMs); int success = 0; int errors = 0; int timeouts = 0; for (int i = 0; i < urls.size(); i++) { GetMethod getMethod = null; try { getMethod = completionService.take().get(); if (getMethod.getStatusCode() >= 300) { ++errors; Assert.assertEquals(getMethod.getResponseBodyAsString(), ERROR_MSG); } else { ++success; Assert.assertEquals(getMethod.getResponseBodyAsString(), SUCCESS_MSG); } } catch (InterruptedException e) { LOGGER.error("Interrupted", e); ++errors; } catch (ExecutionException e) { if (Throwables.getRootCause(e) instanceof SocketTimeoutException) { LOGGER.debug("Timeout"); ++timeouts; } else { LOGGER.error("Error", e); ++errors; } } catch (IOException e) { ++errors; } } Assert.assertEquals(2, success); Assert.assertEquals(1, errors); Assert.assertEquals(1, timeouts); } }