/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 org.apache.brooklyn.policy.enricher; import java.net.URL; import java.util.concurrent.TimeUnit; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.core.test.entity.TestApplication; import org.apache.brooklyn.core.test.entity.TestEntity; import org.apache.brooklyn.policy.enricher.HttpLatencyDetector; import org.apache.brooklyn.test.EntityTestUtils; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.http.BetterMockWebServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; import com.google.common.collect.ImmutableList; import com.google.mockwebserver.MockResponse; public class HttpLatencyDetectorTest { private static final Logger log = LoggerFactory.getLogger(HttpLatencyDetectorTest.class); public static final AttributeSensor<String> TEST_URL = Sensors.newStringSensor( "test.url"); private BetterMockWebServer server; private LocalhostMachineProvisioningLocation loc; private TestApplication app; private TestEntity entity; private URL baseUrl; @BeforeMethod(alwaysRun=true) public void setUp() throws Exception { loc = new LocalhostMachineProvisioningLocation(); app = TestApplication.Factory.newManagedInstanceForTests(); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); app.start(ImmutableList.of(loc)); server = BetterMockWebServer.newInstanceLocalhost(); for (int i = 0; i < 100; i++) { server.enqueue(new MockResponse().setResponseCode(200).addHeader("content-type: application/json").setBody("{\"foo\":\"myfoo\"}")); } server.play(); baseUrl = server.getUrl("/"); } @AfterMethod(alwaysRun=true) public void tearDown() throws Exception { if (server != null) server.shutdown(); if (app != null) Entities.destroyAll(app.getManagementContext()); } @Test(groups="Integration") public void testPollsUrl() throws Exception { entity.sensors().set(TestEntity.SERVICE_UP, true); entity.enrichers().add(HttpLatencyDetector.builder() .url(baseUrl) .rollup(500, TimeUnit.MILLISECONDS) .period(100, TimeUnit.MILLISECONDS) .build()); assertLatencyAttributesNonNull(entity); } @Test(groups="Integration") public void testWaitsForSensorThenPolls() throws Exception { entity.enrichers().add(HttpLatencyDetector.builder() .url(TEST_URL) .noServiceUp() .rollup(500, TimeUnit.MILLISECONDS) .period(100, TimeUnit.MILLISECONDS) .build()); // nothing until url is set EntityTestUtils.assertAttributeEqualsContinually( MutableMap.of("timeout", 200), entity, HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_MOST_RECENT, null); // gets value after url is set, and gets rolling average entity.sensors().set(TEST_URL, baseUrl.toString()); assertLatencyAttributesNonNull(entity); } @Test(groups="Integration") public void testGetsSensorIfAlredySetThenPolls() throws Exception { entity.sensors().set(TEST_URL, baseUrl.toString()); entity.enrichers().add(HttpLatencyDetector.builder() .url(TEST_URL) .noServiceUp() .rollup(500, TimeUnit.MILLISECONDS) .period(100, TimeUnit.MILLISECONDS) .build()); assertLatencyAttributesNonNull(entity); } @Test(groups="Integration") public void testWaitsForServiceUp() throws Exception { entity.sensors().set(TestEntity.SERVICE_UP, false); entity.enrichers().add(HttpLatencyDetector.builder() .url(baseUrl) .period(100, TimeUnit.MILLISECONDS) .build()); // nothing until url is set EntityTestUtils.assertAttributeEqualsContinually( MutableMap.of("timeout", 200), entity, HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_MOST_RECENT, null); // gets value after url is set, and gets rolling average entity.sensors().set(TestEntity.SERVICE_UP, true); assertLatencyAttributesNonNull(entity); } protected void assertLatencyAttributesNonNull(Entity entity) { EntityTestUtils.assertAttributeEventuallyNonNull(entity, HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_MOST_RECENT); EntityTestUtils.assertAttributeEventuallyNonNull(entity, HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_IN_WINDOW); log.info("Latency to "+entity.getAttribute(TEST_URL)+" is "+entity.getAttribute(HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_MOST_RECENT)); log.info("Mean latency to "+entity.getAttribute(TEST_URL)+" is "+entity.getAttribute(HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_IN_WINDOW)); } }