package com.twitter.common.net.http.filters;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.google.common.collect.ImmutableMap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceFilter;
import com.google.inject.servlet.GuiceServletContextListener;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import org.junit.Before;
import org.junit.Test;
import com.twitter.common.net.http.HttpServerDispatch;
import com.twitter.common.net.http.JettyHttpServerDispatch;
import com.twitter.common.stats.Stat;
import com.twitter.common.stats.Stats;
import com.twitter.common.util.Clock;
import com.twitter.common.util.testing.FakeClock;
import static com.sun.jersey.api.core.ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class HttpStatsFilterIntegrationTest {
private Client client;
private FakeClock clock;
private JettyHttpServerDispatch server;
@Before
public void setUp() {
Stats.flush();
server = new JettyHttpServerDispatch();
server.listen(0);
server.registerFilter(GuiceFilter.class, "/*");
clock = new FakeClock();
final Injector injector = Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(TestServlet.class).in(Singleton.class);
bind(Clock.class).toInstance(clock);
bind(HttpStatsFilter.class).in(Singleton.class);
}
},
new JerseyServletModule() {
@Override
protected void configureServlets() {
filter("/*").through(HttpStatsFilter.class);
serve("/*").with(GuiceContainer.class, ImmutableMap.of(
PROPERTY_CONTAINER_RESPONSE_FILTERS, HttpStatsFilter.class.getName()));
}
}
);
server.getRootContext().addEventListener(new GuiceServletContextListener() {
@Override protected Injector getInjector() {
return injector;
}
});
ClientConfig config = new DefaultClientConfig();
client = Client.create(config);
}
@Path("/")
public static class TestServlet {
@GET
@Path("/hello")
@Produces(MediaType.TEXT_PLAIN)
@HttpStatsFilter.TrackRequestStats("hello")
public Response hello() {
return Response.ok("hello world").build();
}
@GET
@Path("/hola")
@Produces(MediaType.TEXT_PLAIN)
@HttpStatsFilter.TrackRequestStats("hola")
public Response hola() {
return Response.ok("hola mundo").build();
}
@GET
@Path("/goodbye")
@Produces(MediaType.TEXT_PLAIN)
public Response goodbye() {
return Response.ok("goodbye cruel world").build();
}
}
private String getResource(String path) {
return client
.resource(String.format("http://localhost:%s%s", server.getPort(), path))
.accept(MediaType.TEXT_PLAIN)
.get(String.class);
}
private void assertStatValue(String statName, long expectedValue) {
Stat<Long> stat = Stats.getVariable(statName);
assertEquals(expectedValue, stat.read().longValue());
}
@Test
public void testStatsTracking() throws Exception {
getResource("/hello");
assertStatValue("http_hello_200_responses_events", 1);
}
@Test
public void testRepeatedContextInjection() throws Exception {
getResource("/hello");
getResource("/hola");
getResource("/hello");
assertStatValue("http_hello_200_responses_events", 2);
assertStatValue("http_hola_200_responses_events", 1);
}
@Test
public void testNoStatsTracking() throws Exception {
getResource("/goodbye");
assertNull(Stats.getVariable("http_goodbye_200_responses_events"));
}
@Test
public void testNoMatchedMethod() throws Exception {
try {
getResource("/what");
fail("Should have thrown a 404.");
} catch (UniformInterfaceException e) {
assertStatValue("http_404_responses_events", 1);
}
}
}