/* * Copyright 2008-2010 Xebia and the original author or authors. * * 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 fr.xebia.management.statistics; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.management.MBeanServer; import javax.management.ObjectInstance; import javax.management.ObjectName; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import fr.xebia.management.statistics.ProfileAspect.ClassNameStyle; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:fr/xebia/management/statistics/test-spring-context.xml") public class ProfileAspectTest { public static class TestService { public String getCountryCode() { return "FR"; } @Profiled(slowInvocationThresholdInMillis = 100, verySlowInvocationThresholdInMillis = 200) public void doJobWithDefaultName() { } @Profiled(name = "my-name") public void doJobWithStaticName() { } @Profiled(name = "test-max-active", maxActive=1) public void testMaxActive() { } @Profiled(name = "test-max-active-with-spel", maxActiveExpression="#{ T(java.lang.Integer).parseInt(systemProperties['tomcat.thread-pool.size']) / 2 }") public void testMaxActiveWithSpel() { } @Profiled(name = "test-max-active-semaphore-acquisition-default", maxActive = 1) public void testMaxActiveSemaphoreAcquisition_default() { } @Profiled(name = "test-max-active-semaphore-acquisition", maxActiveSemaphoreAcquisitionMaxTimeInMillis = 1000, maxActive = 1) public void testMaxActiveSemaphoreAcquisition() { } @Profiled(name = "my-name(#{args[0]}-#{args[1]}-#{invokedObject.countryCode})") public void doJobWithElName(String arg1, String arg2) { } @Profiled(name = "test-slow-invocation-threshold", slowInvocationThresholdInMillis = 50, verySlowInvocationThresholdInMillis = 100) public void testSlowInvocationThreshold() throws InterruptedException { Thread.sleep(75); } @Profiled(name = "test-very-slow-invocation-threshold", slowInvocationThresholdInMillis = 25, verySlowInvocationThresholdInMillis = 50) public void testVerySlowInvocationThreshold() throws InterruptedException { Thread.sleep(75); } } @Autowired protected TestService testService; @Autowired protected ProfileAspect profileAspect; @Autowired protected MBeanServer mbeanServer; @Test public void testProfiledAnnotationWithDefaultName() throws Exception { // test testService.doJobWithDefaultName(); // verify // don't use getClass().getName() because the class is enhanced by CGLib // and its name looks like // "...ProfileAspectTest$TestService$$EnhancerByCGLIB$$9b64fd54" String name = "f.x.m.s.ProfileAspectTest$TestService.doJobWithDefaultName"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); System.out.println(profileAspect.serviceStatisticsByName); assertNotNull(serviceStatistics); assertEquals(1, serviceStatistics.getInvocationCount()); assertEquals(0, serviceStatistics.getSlowInvocationCount()); assertEquals(0, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(0, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(0, serviceStatistics.getTotalExceptionCount()); Set<ObjectInstance> mbeansInstances = mbeanServer.queryMBeans(new ObjectName("com.mycompany:type=ServiceStatistics,name=" + name), null); assertEquals(1, mbeansInstances.size()); ObjectName serviceStatisticsObjectName = mbeansInstances.iterator().next().getObjectName(); assertEquals(1, mbeanServer.getAttribute(serviceStatisticsObjectName, "InvocationCount")); } @Test public void testProfiledAnnotationWithStaticName() throws Exception { // test testService.doJobWithStaticName(); // verify String name = "my-name"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(1, serviceStatistics.getInvocationCount()); assertEquals(0, serviceStatistics.getSlowInvocationCount()); assertEquals(0, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(0, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(0, serviceStatistics.getTotalExceptionCount()); } @Test public void testProfiledAnnotationWithElName() throws Exception { // test testService.doJobWithElName("foo", "bar"); // verify String name = "my-name(foo-bar-FR)"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(1, serviceStatistics.getInvocationCount()); assertEquals(0, serviceStatistics.getSlowInvocationCount()); assertEquals(0, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(0, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(0, serviceStatistics.getTotalExceptionCount()); } @Test public void testSlowInvocationThreshold() throws Exception { // test testService.testSlowInvocationThreshold(); // verify String name = "test-slow-invocation-threshold"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(1, serviceStatistics.getInvocationCount()); assertEquals(1, serviceStatistics.getSlowInvocationCount()); assertEquals(0, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(0, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(0, serviceStatistics.getTotalExceptionCount()); } @Test public void testMaxActive() throws Exception { // initialize testService.testMaxActive(); String name = "test-max-active"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); // simulate one running invocation serviceStatistics.getMaxActiveSemaphore().acquire(); assertEquals(0, serviceStatistics.getMaxActiveSemaphore().availablePermits()); // test try { testService.testMaxActive(); fail("ServiceUnavailableException expected"); } catch(ServiceUnavailableException e) { // expected } // reset serviceStatistics.setMaxActive(1); testService.testMaxActive(); // verify assertEquals(2, serviceStatistics.getInvocationCount()); assertEquals(0, serviceStatistics.getSlowInvocationCount()); assertEquals(0, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(1, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(1, serviceStatistics.getTotalExceptionCount()); } @Test public void testMaxActiveWithSpel() throws Exception { System.setProperty("tomcat.thread-pool.size", "20"); // initialize testService.testMaxActiveWithSpel(); String name = "test-max-active-with-spel"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); int availablePermits = serviceStatistics.getMaxActiveSemaphore().availablePermits(); assertEquals(10, availablePermits); } @Test public void testMaxActive_defaultSemaphoreAcquisition() throws Exception { // initialize testService.testMaxActiveSemaphoreAcquisition_default(); String name = "test-max-active-semaphore-acquisition-default"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS), serviceStatistics.getMaxActiveSemaphoreAcquisitionMaxTimeInNanos()); } @Test(timeout = 5000) public void testMaxActiveSemaphoreAcquisition() throws Exception { // initialize testService.testMaxActiveSemaphoreAcquisition(); String name = "test-max-active-semaphore-acquisition"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(TimeUnit.NANOSECONDS.convert(1000, TimeUnit.MILLISECONDS), serviceStatistics.getMaxActiveSemaphoreAcquisitionMaxTimeInNanos()); serviceStatistics.getMaxActiveSemaphore().acquire(); assertEquals(0, serviceStatistics.getMaxActiveSemaphore().availablePermits()); long start = System.currentTimeMillis(); try { testService.testMaxActiveSemaphoreAcquisition(); fail("ServiceUnavailableException expected"); } catch(ServiceUnavailableException ex) { // Expected } long waited = System.currentTimeMillis() - start; // reset serviceStatistics.setMaxActive(1); testService.testMaxActiveSemaphoreAcquisition(); assertTrue(waited >= 900L); } @Test public void testVerySlowInvocationThreshold() throws Exception { // test testService.testVerySlowInvocationThreshold(); // verify String name = "test-very-slow-invocation-threshold"; ServiceStatistics serviceStatistics = profileAspect.serviceStatisticsByName.get(name); assertNotNull(serviceStatistics); assertEquals(1, serviceStatistics.getInvocationCount()); assertEquals(0, serviceStatistics.getSlowInvocationCount()); assertEquals(1, serviceStatistics.getVerySlowInvocationCount()); assertEquals(0, serviceStatistics.getBusinessExceptionCount()); assertEquals(0, serviceStatistics.getServiceUnavailableExceptionCount()); assertEquals(0, serviceStatistics.getCommunicationExceptionCount()); assertEquals(0, serviceStatistics.getOtherExceptionCount()); assertEquals(0, serviceStatistics.getTotalExceptionCount()); } @Test public void testGetClassNameCompactFullyQualifiedName() { String actual = ProfileAspect .getFullyQualifiedMethodName("java.lang.String", "length", ClassNameStyle.COMPACT_FULLY_QUALIFIED_NAME); assertEquals("j.l.String.length", actual); } @Test public void testGetClassNameFullyQualifiedName() { String actual = ProfileAspect.getFullyQualifiedMethodName("java.lang.String", "length", ClassNameStyle.FULLY_QUALIFIED_NAME); assertEquals("java.lang.String.length", actual); } @Test public void testGetClassNameShortName() { String actual = ProfileAspect.getFullyQualifiedMethodName("java.lang.String", "length", ClassNameStyle.SHORT_NAME); assertEquals("String.length", actual); } @Autowired ServiceStatistics serviceStatistics; @Test public void testServiceStatistics() throws Exception { System.out.println(serviceStatistics); } }