/*
* Copyright 2011 Proofpoint, Inc.
*
* 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.proofpoint.event.monitor;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Modules;
import com.proofpoint.bootstrap.Bootstrap;
import com.proofpoint.bootstrap.LifeCycleManager;
import com.proofpoint.discovery.client.DiscoveryModule;
import com.proofpoint.http.client.ApacheHttpClient;
import com.proofpoint.http.client.FullJsonResponseHandler.JsonResponse;
import com.proofpoint.http.client.HttpClient;
import com.proofpoint.http.client.HttpClientConfig;
import com.proofpoint.http.client.Request;
import com.proofpoint.http.server.testing.TestingHttpServer;
import com.proofpoint.http.server.testing.TestingHttpServerModule;
import com.proofpoint.jaxrs.JaxrsModule;
import com.proofpoint.jmx.JmxHttpModule;
import com.proofpoint.jmx.JmxModule;
import com.proofpoint.json.JsonCodec;
import com.proofpoint.json.JsonModule;
import com.proofpoint.node.testing.TestingNodeModule;
import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.annotation.Nullable;
import javax.management.MBeanServer;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static com.proofpoint.http.client.FullJsonResponseHandler.createFullJsonResponseHandler;
import static com.proofpoint.http.client.Request.Builder.prepareDelete;
import static com.proofpoint.http.client.Request.Builder.prepareGet;
import static com.proofpoint.http.client.Request.Builder.preparePost;
import static com.proofpoint.http.client.StaticBodyGenerator.createStaticBodyGenerator;
import static com.proofpoint.http.client.StatusResponseHandler.createStatusResponseHandler;
import static com.proofpoint.testing.Assertions.assertEqualsIgnoreOrder;
import static java.util.Collections.nCopies;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
public class TestServer
{
private static final JsonCodec<Map<String, Integer>> STATS_CODEC = JsonCodec.mapJsonCodec(String.class, Integer.class);
private static final JsonCodec<Map<String, Object>> MONITOR_CODEC = JsonCodec.mapJsonCodec(String.class, Object.class);
private static final JsonCodec<List<Map<String, Object>>> MONITOR_LIST_CODEC = JsonCodec.listJsonCodec(JsonCodec.mapJsonCodec(String.class, Object.class));
private HttpClient client;
private TestingHttpServer server;
private Monitor scorerHttpMonitor;
private Monitor prsMessageMonitor;
private LifeCycleManager lifeCycleManager;
@BeforeMethod
public void setup()
throws Exception
{
ImmutableMap<String, String> config = ImmutableMap.of("monitor.file", "src/test/resources/monitor.json");
final MBeanServer mockMBeanServer = mock(MBeanServer.class);
Bootstrap app = new Bootstrap(
new TestingNodeModule(),
new TestingHttpServerModule(),
new JsonModule(),
new JaxrsModule(),
new JmxHttpModule(),
Modules.override(new JmxModule()).with(
new Module()
{
@Override
public void configure(Binder binder)
{
binder.bind(MBeanServer.class).toInstance(mockMBeanServer);
}
}),
new DiscoveryModule(),
new MainModule(),
new Module()
{
@Override
public void configure(Binder binder)
{
binder.bind(Alerter.class).to(InMemoryAlerter.class).in(Scopes.SINGLETON);
}
}
).setRequiredConfigurationProperties(config);
Injector injector = app
.doNotInitializeLogging()
.initialize();
lifeCycleManager = injector.getInstance(LifeCycleManager.class);
server = injector.getInstance(TestingHttpServer.class);
Map<String, Monitor> monitors = newHashMap();
for (Monitor monitor : newArrayList(injector.getInstance(Key.get(new TypeLiteral<Set<Monitor>>() { })))) {
monitors.put(monitor.getName(), monitor);
}
Assert.assertEquals(monitors.size(), 6);
scorerHttpMonitor = monitors.get("ScorerHttpMonitor");
Assert.assertNotNull(scorerHttpMonitor);
prsMessageMonitor = monitors.get("PrsMessageMonitor");
Assert.assertNotNull(prsMessageMonitor);
client = new ApacheHttpClient(new HttpClientConfig());
}
@AfterMethod
public void teardown()
throws Exception
{
if (lifeCycleManager != null) {
lifeCycleManager.stop();
}
}
@Test
public void testPostEvents()
throws Exception
{
List<Event> events = newArrayList(concat(
nCopies(3, new Event("HttpRequest", "id", "host", new DateTime(), ImmutableMap.of("requestUri", "/v1/scorer/foo", "responseCode", 204))),
nCopies(5, new Event("not-HttpRequest", "id", "host", new DateTime(), ImmutableMap.<String, Object>of())),
nCopies(7, new Event("HttpRequest", "id", "host", new DateTime(), ImmutableMap.of("requestUri", "/other/path"))),
nCopies(11, new Event("PrsMessage", "id", "host", new DateTime(), ImmutableMap.<String, Object>of())),
nCopies(13, new Event("not-PrsMessage", "id", "host", new DateTime(), ImmutableMap.<String, Object>of())),
nCopies(17, new Event("HttpRequest", "id", "host", new DateTime(), ImmutableMap.of("requestUri", "/v1/scorer/foo", "responseCode", 400)))
));
final String json = JsonCodec.listJsonCodec(Event.class).toJson(events);
Request request = preparePost()
.setUri(urlFor("/v1/event"))
.setHeader("Content-Type", MediaType.APPLICATION_JSON)
.setBodyGenerator(createStaticBodyGenerator(json, Charsets.UTF_8))
.build();
int statusCode = client.execute(request, createStatusResponseHandler()).getStatusCode();
assertEquals(statusCode, Status.NO_CONTENT.getStatusCode());
Assert.assertEquals(scorerHttpMonitor.getEvents().getCount(), 3);
Assert.assertEquals(prsMessageMonitor.getEvents().getCount(), 11);
}
@Test
public void testListMonitors()
throws Exception
{
Request request = prepareGet()
.setUri(urlFor("/v1/monitor"))
.build();
JsonResponse<List<Map<String, Object>>> response = client.execute(request, createFullJsonResponseHandler(MONITOR_LIST_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
List<Map<String,Object>> actual = response.getValue();
Iterable<String> entryNames = Iterables.transform(actual, new Function<Map<String, Object>, String>()
{
@Override
public String apply(@Nullable Map<String, Object> monitor)
{
return (String) monitor.get("name");
}
});
assertEqualsIgnoreOrder(entryNames, ImmutableList.of(
"ScorerHttpMonitor",
"ScorerHttpErrorMonitor",
"PrsMessageMonitor",
"Min",
"Max",
"Between"));
}
@Test
public void testGetMonitorDetail()
throws Exception
{
Request request = prepareGet()
.setUri(urlFor("/v1/monitor/ScorerHttpMonitor"))
.build();
JsonResponse<Map<String, Object>> response = client.execute(request, createFullJsonResponseHandler(MONITOR_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
Map<String, Object> actual = response.getValue();
assertEquals(actual, ImmutableMap.<String, Object>builder()
.put("name", "ScorerHttpMonitor")
.put("ok", true)
.put("minimumOneMinuteRate", 100.0)
.put("oneMinuteRate", 0.0)
.put("fiveMinuteRate", 0.0)
.put("fifteenMinuteRate", 0.0)
.put("self", urlFor("/v1/monitor/ScorerHttpMonitor").toString())
.build());
}
@Test
public void testGetMonitorState()
throws Exception
{
Request request = prepareGet()
.setUri(urlFor("/v1/monitor/ScorerHttpMonitor"))
.build();
JsonResponse<Map<String, Object>> response = client.execute(request, createFullJsonResponseHandler(MONITOR_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
Map<String, Object> before = response.getValue();
assertEquals(before.get("ok"), true);
failHttpScorerMonitor();
request = prepareGet()
.setUri(urlFor("/v1/monitor/ScorerHttpMonitor"))
.build();
response = client.execute(request, createFullJsonResponseHandler(MONITOR_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
Map<String, Object> after = response.getValue();
assertEquals(after.get("ok"), false);
}
@Test
public void testStats()
throws Exception
{
List<Event> events = nCopies(3, new Event("HttpRequest", "id", "host", new DateTime(), ImmutableMap.of("requestUri", "/v1/scorer/foo", "responseCode", 204)));
final String json = JsonCodec.listJsonCodec(Event.class).toJson(events);
Request request = preparePost()
.setUri(urlFor("/v1/event"))
.setHeader("Content-Type", MediaType.APPLICATION_JSON)
.setBodyGenerator(createStaticBodyGenerator(json, Charsets.UTF_8))
.build();
client.execute(request, createStatusResponseHandler());
request = prepareGet()
.setUri(urlFor("/v1/event/stats"))
.build();
JsonResponse<Map<String, Integer>> response = client.execute(request, createFullJsonResponseHandler(STATS_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
assertEquals(response.getValue(), ImmutableMap.of("HttpRequest", 3));
request = prepareDelete()
.setUri(urlFor("/v1/event/stats"))
.build();
assertEquals(client.execute(request, createStatusResponseHandler()).getStatusCode(), Status.NO_CONTENT.getStatusCode());
request = prepareGet()
.setUri(urlFor("/v1/event/stats"))
.build();
response = client.execute(request, createFullJsonResponseHandler(STATS_CODEC));
assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
assertEquals(response.getValue(), ImmutableMap.of());
}
private void failHttpScorerMonitor()
{
for (int i = 0; i < 100; ++i) {
scorerHttpMonitor.getEvents().tick();
}
scorerHttpMonitor.checkState();
}
private URI urlFor(String path)
{
return server.getBaseUrl().resolve(path);
}
}