package io.searchbox.client; import com.google.common.collect.Maps; import io.searchbox.action.Action; import org.junit.Test; import java.io.IOException; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Dogukan Sonmez */ public class AbstractJestClientTest { AbstractJestClient client = new AbstractJestClient() { @Override public <T extends JestResult> T execute(Action<T> clientRequest) throws IOException { return null; // NOOP } @Override public <T extends JestResult> void executeAsync(final Action<T> clientRequest, final JestResultHandler<? super T> resultHandler) { // NOOP } }; @Test public void getRequestURL() { String requestURI = "twitter/tweet/1"; String elasticSearchServer = "http://localhost:9200"; assertEquals("http://localhost:9200/twitter/tweet/1", client.getRequestURL(elasticSearchServer, requestURI)); } @Test public void testGetElasticSearchServer() throws Exception { LinkedHashSet<String> set = new LinkedHashSet<String>(); set.add("http://localhost:9200"); set.add("http://localhost:9300"); set.add("http://localhost:9400"); client.setServers(set); Set<String> serverList = new HashSet<String>(); for (int i = 0; i < 3; i++) { serverList.add(client.getNextServer()); } assertEquals("round robin does not work", 3, serverList.size()); assertTrue(set.contains("http://localhost:9200")); assertTrue(set.contains("http://localhost:9300")); assertTrue(set.contains("http://localhost:9400")); } @Test public void testGetElasticSearchServerIsThreadsafe() throws Exception { final int NUM_THREADS = 12; final int NUM_ITERATIONS = 12000; final int MIN_ACCEPTABLE_PER_SERVER = 3900; final int MAX_ACCEPTABLE_PER_SERVER = 4100; // do NUM_ITERATIONS of getNextServer, across NUM_THREADS // we should ensure that no exceptions are thrown, // and that we get a rather even share of results for each possible server final Set<String> servers = new LinkedHashSet<String>(); servers.add("http://localhost:9200"); servers.add("http://localhost:9300"); servers.add("http://localhost:9400"); client.setServers(servers); final Map<String, AtomicInteger> hits = Maps.newConcurrentMap(); for (String server : servers) { hits.put(server, new AtomicInteger()); } final AtomicInteger numExceptions = new AtomicInteger(); final ExecutorService pool = Executors.newFixedThreadPool(NUM_THREADS); for (int i = 0; i < NUM_ITERATIONS; i++) { if (numExceptions.get() == 0) { // don't bother submitting more if there are exceptions already pool.submit(new Runnable() { @Override public void run() { try { final String nextServer = client.getNextServer(); if (nextServer == null) { throw new IllegalStateException("acquired null server!"); } else if (!hits.containsKey(nextServer)) { throw new IllegalStateException("acquired server " + nextServer + ", but this is unknown!"); } else { hits.get(nextServer).incrementAndGet(); } } catch (Throwable t) { System.err.println("Error occurred: " + t.getMessage()); t.printStackTrace(); numExceptions.incrementAndGet(); } } }); } else { System.err.println("Exception detected, not submitting more."); break; } } pool.shutdown(); pool.awaitTermination(5, TimeUnit.SECONDS); assertEquals("should see 0 exceptions", 0, numExceptions.get()); System.out.println(hits); for (Map.Entry<String, AtomicInteger> entry : hits.entrySet()) { assertTrue("should have roughly same entries in each of the hits buckets but " + entry.getKey() + " has " + entry.getValue(), entry.getValue().get() >= MIN_ACCEPTABLE_PER_SERVER && entry.getValue().get() <= MAX_ACCEPTABLE_PER_SERVER); } } }