/* * Copyright 2010-2011 Ning, Inc. * * Ning 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 com.ning.metrics.goodwill.access; import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.jetty.server.AbstractHttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.bio.SocketConnector; import org.eclipse.jetty.util.thread.ExecutorThreadPool; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; public class CachingGoodwillAccessorTest { private static final int CACHE_TIMEOUT_IN_SECONDS = 3; // 3 seconds private static final String SCHEMA_NAME = "Schema"; private int port; private SocketConnector connector; private Server server; private Server errorServer; private final AtomicInteger serversHits = new AtomicInteger(0); private boolean jettyShouldBomb = false; @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { port = findFreePort(); connector = new SocketConnector(); connector.setHost("127.0.0.1"); connector.setPort(port); server = new Server() { @Override public void handle(AbstractHttpConnection connection) throws IOException, ServletException { serversHits.incrementAndGet(); final Request request = connection.getRequest(); final Response response = connection.getResponse(); if (jettyShouldBomb) { response.setStatus(500); request.setHandled(true); return; } else { response.setStatus(200); } // Create a dummy schema List<GoodwillSchemaField> items = new ArrayList<GoodwillSchemaField>(); items.add(new GoodwillSchemaField(SCHEMA_NAME, "STRING", (short) 0, null, "string", null, null, null)); GoodwillSchema schema = new GoodwillSchema(SCHEMA_NAME, items); // Create the GoodwillSchema store Map<String, List<GoodwillSchema>> payload = new HashMap<String, List<GoodwillSchema>>(); List<GoodwillSchema> list = new ArrayList<GoodwillSchema>(); list.add(schema); payload.put("types", list); // Hardcoded value in Goodwill // Serialize the store and return it ByteArrayOutputStream out = new ByteArrayOutputStream(); (new ObjectMapper()).writeValue(out, payload); out.close(); response.getWriter().print(out.toString()); request.setHandled(true); } }; server.setThreadPool(new ExecutorThreadPool()); server.addConnector(connector); connector.start(); server.start(); } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { server.stop(); connector.stop(); } private int findFreePort() throws IOException { ServerSocket socket = null; try { socket = new ServerSocket(0); return socket.getLocalPort(); } finally { if (socket != null) { socket.close(); } } } @Test(groups = "slow") public void testCachingRegistrar() throws Exception { CachingGoodwillAccessor accessor = new CachingGoodwillAccessor("127.0.0.1", port, CACHE_TIMEOUT_IN_SECONDS); // It will warm the cache on startup - give it some time Thread.sleep(CACHE_TIMEOUT_IN_SECONDS * 1000 / 2); Assert.assertEquals(serversHits.get(), 1); // The caching accessor will hit the server if the schema does not exist GoodwillSchema schema = accessor.getSchema("Doesn'tExist"); Assert.assertNull(schema); Assert.assertEquals(serversHits.get(), 2); // Try again schema = accessor.getSchema("Doesn'tExist"); Assert.assertNull(schema); Assert.assertEquals(serversHits.get(), 3); // Valid schema in the cache shouldn't trigger a hit schema = accessor.getSchema(SCHEMA_NAME); Assert.assertNotNull(schema); Assert.assertEquals(serversHits.get(), 3); // No hit! // Test backend thread Thread.sleep(CACHE_TIMEOUT_IN_SECONDS * 1000); Assert.assertEquals(serversHits.get(), 4); // Refresh // We shouldn't care if Goodwill is down jettyShouldBomb = true; // The good schema is cached schema = accessor.getSchema(SCHEMA_NAME); Assert.assertNotNull(schema); Assert.assertEquals(serversHits.get(), 4); // The bad schemas are not schema = accessor.getSchema("NewOne"); Assert.assertNull(schema); Assert.assertEquals(serversHits.get(), 5); accessor.close(); } }