/* * Copyright 2008-2017 by Emeric Vernat * * This file is part of Java Melody. * * 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 net.bull.javamelody; // NOPMD import static net.bull.javamelody.HttpParameters.ACTION_PARAMETER; import static net.bull.javamelody.HttpParameters.CACHE_ID_PARAMETER; import static net.bull.javamelody.HttpParameters.CACHE_KEYS_PART; import static net.bull.javamelody.HttpParameters.CLASS_PARAMETER; import static net.bull.javamelody.HttpParameters.COLLECTOR_PARAMETER; import static net.bull.javamelody.HttpParameters.CONNECTIONS_PART; import static net.bull.javamelody.HttpParameters.COUNTER_PARAMETER; import static net.bull.javamelody.HttpParameters.COUNTER_SUMMARY_PER_CLASS_PART; import static net.bull.javamelody.HttpParameters.CURRENT_REQUESTS_PART; import static net.bull.javamelody.HttpParameters.DATABASE_PART; import static net.bull.javamelody.HttpParameters.DEFAULT_WITH_CURRENT_REQUESTS_PART; import static net.bull.javamelody.HttpParameters.DEPENDENCIES_PART; import static net.bull.javamelody.HttpParameters.EXPLAIN_PLAN_PART; import static net.bull.javamelody.HttpParameters.FORMAT_PARAMETER; import static net.bull.javamelody.HttpParameters.GRAPH_PARAMETER; import static net.bull.javamelody.HttpParameters.GRAPH_PART; import static net.bull.javamelody.HttpParameters.HEIGHT_PARAMETER; import static net.bull.javamelody.HttpParameters.HOTSPOTS_PART; import static net.bull.javamelody.HttpParameters.JMX_VALUE; import static net.bull.javamelody.HttpParameters.JNDI_PART; import static net.bull.javamelody.HttpParameters.JNLP_PART; import static net.bull.javamelody.HttpParameters.JROBINS_PART; import static net.bull.javamelody.HttpParameters.JVM_PART; import static net.bull.javamelody.HttpParameters.LAST_VALUE_PART; import static net.bull.javamelody.HttpParameters.MBEANS_PART; import static net.bull.javamelody.HttpParameters.OTHER_JROBINS_PART; import static net.bull.javamelody.HttpParameters.PART_PARAMETER; import static net.bull.javamelody.HttpParameters.PERIOD_PARAMETER; import static net.bull.javamelody.HttpParameters.POM_XML_PART; import static net.bull.javamelody.HttpParameters.PROCESSES_PART; import static net.bull.javamelody.HttpParameters.REPORT_PARAMETER; import static net.bull.javamelody.HttpParameters.REQUEST_PARAMETER; import static net.bull.javamelody.HttpParameters.RESOURCE_PARAMETER; import static net.bull.javamelody.HttpParameters.RUNTIME_DEPENDENCIES_PART; import static net.bull.javamelody.HttpParameters.SESSIONS_PART; import static net.bull.javamelody.HttpParameters.SESSION_ID_PARAMETER; import static net.bull.javamelody.HttpParameters.SOURCE_PART; import static net.bull.javamelody.HttpParameters.SPRING_BEANS_PART; import static net.bull.javamelody.HttpParameters.THREADS_DUMP_PART; import static net.bull.javamelody.HttpParameters.THREADS_PART; import static net.bull.javamelody.HttpParameters.USAGES_PART; import static net.bull.javamelody.HttpParameters.WEBAPP_VERSIONS_PART; import static net.bull.javamelody.HttpParameters.WEB_XML_PART; import static net.bull.javamelody.HttpParameters.WIDTH_PARAMETER; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.SQLException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.Set; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ReadListener; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; /** * Test unitaire de la classe MonitoringFilter. * @author Emeric Vernat */ // CHECKSTYLE:OFF public class TestMonitoringFilter { // CHECKSTYLE:ON private static final String FILTER_NAME = "monitoring"; // identique à HttpCookieManager.PERIOD_COOKIE_NAME private static final String PERIOD_COOKIE_NAME = "javamelody.period"; private static final String REMOTE_ADDR = "127.0.0.1"; // NOPMD private static final String CONTEXT_PATH = "/test"; private static final String GRAPH = "graph"; private static final String TRUE = "true"; private MonitoringFilter monitoringFilter; /** * Initialisation (deux Before ne garantissent pas l'ordre dans Eclipse). */ public TestMonitoringFilter() { super(); Utils.initialize(); } /** * Initialisation. * @throws ServletException e */ @Before public void setUp() throws ServletException { try { final Field field = MonitoringFilter.class.getDeclaredField("instanceCreated"); field.setAccessible(true); field.set(null, false); } catch (final IllegalAccessException e) { throw new IllegalStateException(e); } catch (final NoSuchFieldException e) { throw new IllegalStateException(e); } final FilterConfig config = createNiceMock(FilterConfig.class); final ServletContext context = createNiceMock(ServletContext.class); expect(config.getServletContext()).andReturn(context).anyTimes(); expect(config.getFilterName()).andReturn(FILTER_NAME).anyTimes(); // anyTimes sur getInitParameter car TestJdbcDriver a pu fixer la propriété système à false expect(context.getInitParameter( Parameters.PARAMETER_SYSTEM_PREFIX + Parameter.DISABLED.getCode())).andReturn(null) .anyTimes(); expect(config.getInitParameter(Parameter.DISABLED.getCode())).andReturn(null).anyTimes(); expect(context.getMajorVersion()).andReturn(2).anyTimes(); expect(context.getMinorVersion()).andReturn(5).anyTimes(); expect(context.getServletContextName()).andReturn("test webapp").anyTimes(); // mockJetty pour avoir un applicationServerIconName dans JavaInformations expect(context.getServerInfo()).andReturn("mockJetty").anyTimes(); // dependencies pour avoir des dépendances dans JavaInformations final Set<String> dependencies = new LinkedHashSet<String>( Arrays.asList("/WEB-INF/lib/jrobin.jar", "/WEB-INF/lib/javamelody.jar")); // et flags pour considérer que les ressources pom.xml et web.xml existent JavaInformations.setWebXmlExistsAndPomXmlExists(true, true); expect(context.getResourcePaths("/WEB-INF/lib/")).andReturn(dependencies).anyTimes(); expect(context.getContextPath()).andReturn(CONTEXT_PATH).anyTimes(); monitoringFilter = new MonitoringFilter(); monitoringFilter.setApplicationType("Test"); replay(config); replay(context); monitoringFilter.init(config); verify(config); verify(context); } /** Test. * @throws ServletException e */ @Test public void testLog() throws ServletException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); expect(request.getRemoteAddr()).andReturn(REMOTE_ADDR); expect(request.getRequestURI()).andReturn("/test/request"); expect(request.getContextPath()).andReturn(CONTEXT_PATH); expect(request.getQueryString()).andReturn("param1=1"); expect(request.getMethod()).andReturn("GET"); setProperty(Parameter.LOG, TRUE); setUp(); replay(request); monitoringFilter.log(request, "test", 1000, false, 10000); verify(request); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilterNoHttp() throws ServletException, IOException { final FilterChain servletChain = createNiceMock(FilterChain.class); final ServletRequest servletRequest = createNiceMock(ServletRequest.class); final ServletResponse servletResponse = createNiceMock(ServletResponse.class); replay(servletRequest); replay(servletResponse); replay(servletChain); monitoringFilter.doFilter(servletRequest, servletResponse, servletChain); verify(servletRequest); verify(servletResponse); verify(servletChain); final FilterChain servletChain2 = createNiceMock(FilterChain.class); final HttpServletRequest servletRequest2 = createNiceMock(HttpServletRequest.class); final ServletResponse servletResponse2 = createNiceMock(ServletResponse.class); replay(servletRequest2); replay(servletResponse2); replay(servletChain2); monitoringFilter.doFilter(servletRequest2, servletResponse2, servletChain2); verify(servletRequest2); verify(servletResponse2); verify(servletChain2); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilter() throws ServletException, IOException { // displayed-counters setProperty(Parameter.DISPLAYED_COUNTERS, "sql"); try { setUp(); doFilter(createNiceMock(HttpServletRequest.class)); setProperty(Parameter.DISPLAYED_COUNTERS, ""); setUp(); doFilter(createNiceMock(HttpServletRequest.class)); setProperty(Parameter.DISPLAYED_COUNTERS, "unknown"); try { setUp(); doFilter(createNiceMock(HttpServletRequest.class)); } catch (final IllegalArgumentException e) { assertNotNull("ok", e); } } finally { setProperty(Parameter.DISPLAYED_COUNTERS, null); } // url exclue setProperty(Parameter.URL_EXCLUDE_PATTERN, ".*"); try { setUp(); doFilter(createNiceMock(HttpServletRequest.class)); } finally { setProperty(Parameter.URL_EXCLUDE_PATTERN, ""); } // standard setUp(); doFilter(createNiceMock(HttpServletRequest.class)); // log setUp(); setProperty(Parameter.LOG, TRUE); try { ((Logger) org.slf4j.LoggerFactory.getLogger(FILTER_NAME)).setLevel(Level.WARN); doFilter(createNiceMock(HttpServletRequest.class)); ((Logger) org.slf4j.LoggerFactory.getLogger(FILTER_NAME)).setLevel(Level.DEBUG); doFilter(createNiceMock(HttpServletRequest.class)); final HttpServletRequest request = createNiceMock(HttpServletRequest.class); expect(request.getHeader("X-Forwarded-For")).andReturn("me").anyTimes(); expect(request.getQueryString()).andReturn("param1=1").anyTimes(); doFilter(request); } finally { setProperty(Parameter.LOG, null); } // ajax final HttpServletRequest request = createNiceMock(HttpServletRequest.class); expect(request.getHeader("X-Requested-With")).andReturn("XMLHttpRequest"); doFilter(request); // erreur système http, avec log setProperty(Parameter.LOG, TRUE); try { final String test = "test"; doFilter(createNiceMock(HttpServletRequest.class), new UnknownError(test)); doFilter(createNiceMock(HttpServletRequest.class), new IllegalStateException(test)); // pas possibles: // doFilter(createNiceMock(HttpServletRequest.class), new IOException(test)); // doFilter(createNiceMock(HttpServletRequest.class), new ServletException(test)); // doFilter(createNiceMock(HttpServletRequest.class), new Exception(test)); } finally { setProperty(Parameter.LOG, null); } setProperty(Parameter.RUM_ENABLED, TRUE); try { setUp(); final HttpServletRequest requestForRum = createNiceMock(HttpServletRequest.class); expect(requestForRum.getHeader("accept")).andReturn("text/html"); expect(requestForRum.getInputStream()) .andReturn(createInputStreamForString("<html><body>test</body></html>")) .anyTimes(); doFilter(requestForRum); } finally { setProperty(Parameter.RUM_ENABLED, null); } } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilterWithSession() throws ServletException, IOException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); final HttpSession session = createNiceMock(HttpSession.class); expect(request.getSession(false)).andReturn(session); expect(request.getLocale()).andReturn(Locale.FRANCE); replay(session); doFilter(request); verify(session); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilterWithSessionBis() throws ServletException, IOException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); final HttpSession session = createNiceMock(HttpSession.class); expect(request.getSession(false)).andReturn(session); // Locale sans pays expect(request.getLocale()).andReturn(Locale.FRENCH).anyTimes(); // "X-Forwarded-For" expect(request.getHeader("X-Forwarded-For")).andReturn("somewhere").anyTimes(); // getRemoteUser expect(request.getRemoteUser()).andReturn("me").anyTimes(); replay(session); doFilter(request); verify(session); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilterWithSessionTer() throws ServletException, IOException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); final HttpSession session = createNiceMock(HttpSession.class); expect(request.getSession(false)).andReturn(session); expect(session.getAttribute(SessionInformations.SESSION_COUNTRY_KEY)) .andReturn(Locale.FRANCE.getCountry()).anyTimes(); expect(session.getAttribute(SessionInformations.SESSION_REMOTE_ADDR)).andReturn("somewhere") .anyTimes(); expect(session.getAttribute(SessionInformations.SESSION_REMOTE_USER)).andReturn("me") .anyTimes(); replay(session); doFilter(request); verify(session); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoFilterWithGWT() throws ServletException, IOException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); final String textGwtRpc = "text/x-gwt-rpc"; expect(request.getContentType()).andReturn(textGwtRpc).anyTimes(); expect(request.getInputStream()) .andReturn(createInputStreamForString("1|2|3|4|5|6|7|8|9|10")).anyTimes(); doFilter(request); final HttpServletRequest request2a = createNiceMock(HttpServletRequest.class); expect(request2a.getContentType()).andReturn("not/x-gwt-rpc").anyTimes(); expect(request2a.getInputStream()) .andReturn(createInputStreamForString("1|2|3|4|5|6|7|8|9|10")).anyTimes(); doFilter(request2a); final HttpServletRequest request2b = createNiceMock(HttpServletRequest.class); expect(request2b.getContentType()).andReturn(textGwtRpc).anyTimes(); expect(request2b.getInputStream()).andReturn(createInputStreamForString("1|2|3|4|5|6")) .anyTimes(); expect(request2b.getReader()).andReturn(new BufferedReader(new StringReader("1|2|3|4|5|6"))) .anyTimes(); replay(request2b); final PayloadNameRequestWrapper wrapper2b = new PayloadNameRequestWrapper(request2b); wrapper2b.getInputStream().read(); wrapper2b.getReader().read(); verify(request2b); final HttpServletRequest request2 = createNiceMock(HttpServletRequest.class); expect(request2.getContentType()).andReturn(textGwtRpc).anyTimes(); expect(request2.getInputStream()) .andReturn(createInputStreamForString("1|2|3|4|5|6||8|9|10")).anyTimes(); expect(request2.getReader()).andReturn(new BufferedReader(new StringReader("1|2|3|4|5|6"))) .anyTimes(); replay(request2); final PayloadNameRequestWrapper wrapper2 = new PayloadNameRequestWrapper(request2); wrapper2.getInputStream().read(); wrapper2.getReader().read(); verify(request2); final HttpServletRequest request3 = createNiceMock(HttpServletRequest.class); expect(request3.getContentType()).andReturn(textGwtRpc).anyTimes(); expect(request3.getCharacterEncoding()).andReturn("utf-8").anyTimes(); expect(request3.getInputStream()) .andReturn(createInputStreamForString("1|2|3|4|5|6||8|9|10")).anyTimes(); expect(request3.getReader()).andReturn(new BufferedReader(new StringReader("1|2|3|4|5|6"))) .anyTimes(); replay(request3); final PayloadNameRequestWrapper wrapper3 = new PayloadNameRequestWrapper(request3); wrapper3.getInputStream().read(); wrapper3.getInputStream().read(); wrapper3.getReader().read(); wrapper3.getReader().read(); verify(request3); } private ServletInputStream createInputStreamForString(final String string) { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( string.getBytes()); // CHECKSTYLE:OFF final ServletInputStream inputStream = new ServletInputStream() { // CHECKSTYLE:ON @Override public int read() throws IOException { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { // nothing } }; return inputStream; } private void doFilter(HttpServletRequest request) throws ServletException, IOException { doFilter(request, null); } private void doFilter(HttpServletRequest request, Throwable exceptionInDoFilter) throws ServletException, IOException { final FilterChain chain = createNiceMock(FilterChain.class); expect(request.getRequestURI()).andReturn("/test/request").anyTimes(); expect(request.getContextPath()).andReturn(CONTEXT_PATH).anyTimes(); expect(request.getMethod()).andReturn("GET").anyTimes(); if (exceptionInDoFilter != null) { // cela fera une erreur système http comptée dans les stats expect(request.getRemoteUser()).andThrow(exceptionInDoFilter); } final HttpServletResponse response = createNiceMock(HttpServletResponse.class); replay(request); replay(response); replay(chain); if (exceptionInDoFilter != null) { try { monitoringFilter.doFilter(request, response, chain); } catch (final Throwable t) { // NOPMD assertNotNull("ok", t); } } else { monitoringFilter.doFilter(request, response, chain); } verify(request); verify(response); verify(chain); } /** Test. * @throws IOException e */ @Test public void testFilterServletResponseWrapper() throws IOException { final HttpServletResponse response = createNiceMock(HttpServletResponse.class); expect(response.getOutputStream()) .andReturn(new FilterServletOutputStream(new ByteArrayOutputStream())).anyTimes(); expect(response.getCharacterEncoding()).andReturn("ISO-8859-1").anyTimes(); final CounterServletResponseWrapper wrappedResponse = new CounterServletResponseWrapper( response); replay(response); assertNotNull("getOutputStream", wrappedResponse.getOutputStream()); assertNotNull("getOutputStream bis", wrappedResponse.getOutputStream()); assertNotNull("getOutputStream", wrappedResponse.getCharacterEncoding()); wrappedResponse.close(); verify(response); final HttpServletResponse response2 = createNiceMock(HttpServletResponse.class); expect(response2.getOutputStream()) .andReturn(new FilterServletOutputStream(new ByteArrayOutputStream())).anyTimes(); expect(response2.getCharacterEncoding()).andReturn(null).anyTimes(); final CounterServletResponseWrapper wrappedResponse2 = new CounterServletResponseWrapper( response); replay(response2); assertNotNull("getWriter", wrappedResponse2.getWriter()); assertNotNull("getWriter bis", wrappedResponse2.getWriter()); wrappedResponse2.close(); verify(response2); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoring() throws ServletException, IOException { monitoring(Collections.<String, String> emptyMap()); monitoring(Collections.<String, String> singletonMap(FORMAT_PARAMETER, "html")); monitoring(Collections.<String, String> singletonMap(FORMAT_PARAMETER, "htmlbody")); setProperty(Parameter.DISABLED, Boolean.TRUE.toString()); try { setUp(); monitoring(Collections.<String, String> emptyMap(), false); } finally { monitoringFilter.destroy(); setProperty(Parameter.DISABLED, Boolean.FALSE.toString()); } setProperty(Parameter.NO_DATABASE, Boolean.TRUE.toString()); try { setUp(); monitoring(Collections.<String, String> emptyMap()); } finally { setProperty(Parameter.NO_DATABASE, Boolean.FALSE.toString()); } setProperty(Parameter.ALLOWED_ADDR_PATTERN, "256.*"); try { setUp(); monitoring(Collections.<String, String> emptyMap(), false); setProperty(Parameter.ALLOWED_ADDR_PATTERN, ".*"); setUp(); monitoring(Collections.<String, String> emptyMap(), false); } finally { setProperty(Parameter.ALLOWED_ADDR_PATTERN, null); } setProperty(Parameter.AUTHORIZED_USERS, "admin:password, "); try { setUp(); monitoring(Collections.<String, String> emptyMap(), false); setProperty(Parameter.AUTHORIZED_USERS, ""); setUp(); monitoring(Collections.<String, String> emptyMap(), false); } finally { setProperty(Parameter.AUTHORIZED_USERS, null); } setProperty(Parameter.MONITORING_PATH, "/admin/monitoring"); try { setUp(); monitoring(Collections.<String, String> emptyMap(), false); } finally { setProperty(Parameter.MONITORING_PATH, "/monitoring"); } try { setProperty(Parameter.JMX_EXPOSE_ENABLED, Boolean.TRUE.toString()); setUp(); monitoring(Collections.<String, String> emptyMap()); } finally { monitoringFilter.destroy(); setProperty(Parameter.JMX_EXPOSE_ENABLED, null); } try { setProperty(Parameter.RUM_ENABLED, Boolean.TRUE.toString()); setUp(); monitoring(Collections.<String, String> emptyMap()); monitoring(Collections.<String, String> singletonMap(RESOURCE_PARAMETER, "boomerang.min.js")); monitoring(Collections.<String, String> singletonMap(PART_PARAMETER, HttpParameters.RUM_PART), false); } finally { monitoringFilter.destroy(); setProperty(Parameter.RUM_ENABLED, null); } } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithMail() throws ServletException, IOException { setProperty(Parameter.MAIL_SESSION, "testmailsession"); setProperty(Parameter.ADMIN_EMAILS, null); setUp(); monitoring(Collections.<String, String> emptyMap()); setProperty(Parameter.ADMIN_EMAILS, "evernat@free.fr"); setUp(); monitoring(Collections.<String, String> emptyMap()); setProperty(Parameter.MAIL_SESSION, null); setProperty(Parameter.ADMIN_EMAILS, null); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithPeriod() throws ServletException, IOException { monitoring( Collections.<String, String> singletonMap(PERIOD_PARAMETER, Period.JOUR.getCode())); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithResource() throws ServletException, IOException { monitoring(Collections.<String, String> singletonMap(RESOURCE_PARAMETER, "monitoring.css")); monitoring(Collections.<String, String> singletonMap(RESOURCE_PARAMETER, "beans.png")); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithGraph() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(GRAPH, "usedMemory"); parameters.put("width", "800"); parameters.put("height", "600"); monitoring(parameters); parameters.put(GRAPH, "unknown"); monitoring(parameters, false); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithParts() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(PART_PARAMETER, CURRENT_REQUESTS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, THREADS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, THREADS_DUMP_PART); monitoring(parameters); parameters.put(PART_PARAMETER, CACHE_KEYS_PART); final String cacheName = getClass().getName(); CacheManager.getInstance().addCache(cacheName); parameters.put(CACHE_ID_PARAMETER, cacheName); monitoring(parameters); CacheManager.getInstance().getCache(cacheName).put(new Element("1", "value")); monitoring(parameters); parameters.put(FORMAT_PARAMETER, "htmlbody"); monitoring(parameters); CacheManager.getInstance().removeCache(cacheName); parameters.remove(CACHE_ID_PARAMETER); parameters.remove(FORMAT_PARAMETER); parameters.put(PART_PARAMETER, JNLP_PART); monitoring(parameters); parameters.put(PART_PARAMETER, DEPENDENCIES_PART); monitoring(parameters); parameters.put(PART_PARAMETER, COUNTER_SUMMARY_PER_CLASS_PART); parameters.put(COUNTER_PARAMETER, "services"); monitoring(parameters); parameters.put(GRAPH, "unknown service"); monitoring(parameters); parameters.remove(COUNTER_PARAMETER); doMonitoringWithGraphPart(); doMonitoringWithSourcePart(); doMonitoringWithUnknownPart(); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithPartsForSystemActions() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); parameters.put(PART_PARAMETER, PROCESSES_PART); monitoring(parameters); monitorJdbcParts(parameters); // il ne faut pas faire un heapHisto sans thread comme dans TestHtmlHeapHistogramReport // parameters.put(PART_PARAMETER, HEAP_HISTO_PART); // monitoring(parameters); monitoringSessionsPart(parameters); parameters.put(PART_PARAMETER, WEB_XML_PART); monitoring(parameters, false); parameters.put(PART_PARAMETER, POM_XML_PART); monitoring(parameters, false); parameters.put(PART_PARAMETER, JNDI_PART); monitoring(parameters); parameters.put(PART_PARAMETER, MBEANS_PART); monitoring(parameters); final ApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "net/bull/javamelody/monitoring-spring.xml", }); context.getBeanDefinitionNames(); parameters.put(PART_PARAMETER, SPRING_BEANS_PART); monitoring(parameters); setProperty(Parameter.SAMPLING_SECONDS, "60"); setUp(); parameters.put(PART_PARAMETER, HOTSPOTS_PART); monitoring(parameters); parameters.remove(PART_PARAMETER); parameters.put(JMX_VALUE, "java.lang:type=OperatingSystem.ProcessCpuTime"); monitoring(parameters); parameters.remove(JMX_VALUE); } /** * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithReportParameter() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(REPORT_PARAMETER, "customReport"); System.setProperty(Parameters.PARAMETER_SYSTEM_PREFIX + "customReport", ""); monitoring(parameters, false); System.setProperty(Parameters.PARAMETER_SYSTEM_PREFIX + "customReport", "test"); monitoring(parameters, false); System.setProperty(Parameters.PARAMETER_SYSTEM_PREFIX + "customReport", "/test"); monitoring(parameters, false); parameters.remove(REPORT_PARAMETER); } private void doMonitoringWithUnknownPart() throws IOException, ServletException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(PART_PARAMETER, "unknown part"); boolean exception = false; try { monitoring(parameters); } catch (final IllegalArgumentException e) { exception = true; } assertTrue("exception if unknown part", exception); } private void monitoringSessionsPart(final Map<String, String> parameters) throws IOException, ServletException { parameters.put(PART_PARAMETER, SESSIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, SESSIONS_PART); parameters.put(SESSION_ID_PARAMETER, "expired session"); monitoring(parameters); parameters.remove(SESSION_ID_PARAMETER); } private void doMonitoringWithGraphPart() throws IOException, ServletException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(PART_PARAMETER, GRAPH); parameters.put(GRAPH, "usedMemory"); monitoring(parameters); parameters.put(PART_PARAMETER, LAST_VALUE_PART); parameters.put(GRAPH, "usedMemory,cpu,unknown"); monitoring(parameters); parameters.put(PART_PARAMETER, USAGES_PART); parameters.put(GRAPH, "unknown"); monitoring(parameters); } private void doMonitoringWithSourcePart() throws IOException, ServletException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(PART_PARAMETER, SOURCE_PART); // classe java du jdk parameters.put(CLASS_PARAMETER, "java.lang.String"); monitoring(parameters); // classe interne dans le même fichier parameters.put(CLASS_PARAMETER, "java.lang.Thread$State"); monitoring(parameters); // classe javax du jdk parameters.put(CLASS_PARAMETER, "javax.naming.InitialContext"); monitoring(parameters); // classe inexistante parameters.put(CLASS_PARAMETER, "java.dummy"); monitoring(parameters); // classe d'un jar construit par Maven parameters.put(CLASS_PARAMETER, "org.jrobin.core.RrdDb"); monitoring(parameters); // classe d'un jar construit par Maven, sans sources parameters.put(CLASS_PARAMETER, "org.apache.tomcat.dbcp.dbcp.BasicDataSource"); monitoring(parameters); // classe d'un jar non construit par Maven parameters.put(CLASS_PARAMETER, "com.lowagie.text.Document"); monitoring(parameters); parameters.remove(CLASS_PARAMETER); } private void monitorJdbcParts(Map<String, String> parameters) throws IOException, ServletException { final Connection connection = TestDatabaseInformations.initH2(); try { parameters.put(PART_PARAMETER, DATABASE_PART); monitoring(parameters); parameters.put(PART_PARAMETER, DATABASE_PART); parameters.put(REQUEST_PARAMETER, "0"); monitoring(parameters); parameters.put(PART_PARAMETER, CONNECTIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, CONNECTIONS_PART); parameters.put(FORMAT_PARAMETER, "htmlbody"); monitoring(parameters); parameters.remove(FORMAT_PARAMETER); parameters.put(REQUEST_PARAMETER, "0"); monitoring(parameters); parameters.remove(REQUEST_PARAMETER); } finally { try { connection.close(); } catch (final SQLException e) { LOG.warn(e.toString(), e); } } } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithActions() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); parameters.put(ACTION_PARAMETER, Action.GC.toString()); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.INVALIDATE_SESSIONS.toString()); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.INVALIDATE_SESSION.toString()); parameters.put(SESSION_ID_PARAMETER, "123456789"); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.CLEAR_CACHES.toString()); monitoring(parameters); if (CacheManager.getInstance().getCache("test clear") == null) { CacheManager.getInstance().addCache("test clear"); } monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.PAUSE_JOB.toString()); parameters.put("jobId", "all"); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.RESUME_JOB.toString()); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.CLEAR_COUNTER.toString()); parameters.put("counter", "all"); monitoring(parameters); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithFormatPdf() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(FORMAT_PARAMETER, "pdf"); monitoring(parameters); parameters.put(PART_PARAMETER, RUNTIME_DEPENDENCIES_PART); parameters.put(COUNTER_PARAMETER, "services"); monitoring(parameters); parameters.remove(COUNTER_PARAMETER); parameters.put(PART_PARAMETER, CURRENT_REQUESTS_PART); monitoring(parameters); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); parameters.put(PART_PARAMETER, SESSIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, PROCESSES_PART); monitoring(parameters); parameters.put(PART_PARAMETER, MBEANS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, COUNTER_SUMMARY_PER_CLASS_PART); parameters.put(COUNTER_PARAMETER, "guice"); monitoring(parameters); parameters.remove(COUNTER_PARAMETER); TestDatabaseInformations.initJdbcDriverParameters(); parameters.put(PART_PARAMETER, DATABASE_PART); monitoring(parameters); setProperty(Parameter.SAMPLING_SECONDS, "60"); setUp(); parameters.put(PART_PARAMETER, HOTSPOTS_PART); monitoring(parameters); // il ne faut pas faire un heapHisto sans thread comme dans TestHtmlHeapHistogramReport // parameters.put(PART_PARAMETER, HEAP_HISTO_PART); // monitoring(parameters); parameters.put(PART_PARAMETER, GRAPH); parameters.put(GRAPH, "usedMemory"); monitoring(parameters); parameters.remove(GRAPH); parameters.put(PART_PARAMETER, "unknown part"); boolean exception = false; try { monitoring(parameters); } catch (final Exception e) { exception = true; } assertTrue("exception if unknown part", exception); } /** Test. * @throws ServletException e * @throws IOException e */ // CHECKSTYLE:OFF @Test // CHECKSTYLE:ON public void testDoMonitoringWithFormatSerialized() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(FORMAT_PARAMETER, TransportFormat.SERIALIZED.getCode()); monitoring(parameters); parameters.put(JMX_VALUE, "java.lang:type=OperatingSystem.ProcessCpuTime"); monitoring(parameters); parameters.remove(JMX_VALUE); parameters.put(PART_PARAMETER, LAST_VALUE_PART); parameters.put(GRAPH, "usedMemory,cpu,unknown"); monitoring(parameters); parameters.remove(GRAPH); setProperty(Parameter.SAMPLING_SECONDS, "60"); setUp(); parameters.put(PART_PARAMETER, HOTSPOTS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, JVM_PART); monitoring(parameters); parameters.put(PART_PARAMETER, THREADS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, CURRENT_REQUESTS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, DEFAULT_WITH_CURRENT_REQUESTS_PART); monitoring(parameters); parameters.put(WIDTH_PARAMETER, "80"); parameters.put(HEIGHT_PARAMETER, "80"); parameters.put(PART_PARAMETER, JROBINS_PART); monitoring(parameters); parameters.put(GRAPH_PARAMETER, "cpu"); parameters.put(PART_PARAMETER, JROBINS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, GRAPH_PART); monitoring(parameters); parameters.remove(GRAPH_PARAMETER); parameters.put(PART_PARAMETER, OTHER_JROBINS_PART); monitoring(parameters); parameters.remove(WIDTH_PARAMETER); parameters.remove(HEIGHT_PARAMETER); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); monitoring(parameters); monitoringSessionsPart(parameters); parameters.put(PART_PARAMETER, PROCESSES_PART); monitoring(parameters); parameters.put(PART_PARAMETER, JNDI_PART); monitoring(parameters); parameters.put(PART_PARAMETER, MBEANS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, DEPENDENCIES_PART); monitoring(parameters); TestDatabaseInformations.initJdbcDriverParameters(); parameters.put(PART_PARAMETER, DATABASE_PART); monitoring(parameters); parameters.put(REQUEST_PARAMETER, "0"); monitoring(parameters); parameters.put(PART_PARAMETER, EXPLAIN_PLAN_PART); parameters.put(REQUEST_PARAMETER, "select 1 from dual"); monitoring(parameters); parameters.remove(REQUEST_PARAMETER); parameters.put(PART_PARAMETER, CONNECTIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, COUNTER_SUMMARY_PER_CLASS_PART); parameters.put(COUNTER_PARAMETER, "guice"); monitoring(parameters); parameters.put(PERIOD_PARAMETER, "jour"); monitoring(parameters); parameters.remove(COUNTER_PARAMETER); parameters.remove(PERIOD_PARAMETER); parameters.put(PART_PARAMETER, WEBAPP_VERSIONS_PART); monitoring(parameters); // il ne faut pas faire un heapHisto sans thread comme dans TestHtmlHeapHistogramReport // parameters.put(PART_PARAMETER, HEAP_HISTO_PART); // monitoring(parameters); parameters.put(PART_PARAMETER, null); parameters.put(COLLECTOR_PARAMETER, "stop"); monitoring(parameters); parameters.put(ACTION_PARAMETER, Action.GC.toString()); monitoring(parameters); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithFormatXml() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(FORMAT_PARAMETER, TransportFormat.XML.getCode()); monitoring(parameters); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); parameters.put(PART_PARAMETER, SESSIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, PROCESSES_PART); monitoring(parameters); TestDatabaseInformations.initJdbcDriverParameters(); parameters.put(PART_PARAMETER, DATABASE_PART); monitoring(parameters); parameters.put(PART_PARAMETER, CONNECTIONS_PART); monitoring(parameters); // il ne faut pas faire un heapHisto sans thread comme dans TestHtmlHeapHistogramReport // parameters.put(PART_PARAMETER, HEAP_HISTO_PART); // monitoring(parameters); } /** Test. * @throws ServletException e * @throws IOException e */ @Test public void testDoMonitoringWithFormatJson() throws ServletException, IOException { final Map<String, String> parameters = new HashMap<String, String>(); parameters.put(FORMAT_PARAMETER, TransportFormat.JSON.getCode()); monitoring(parameters); parameters.put(PART_PARAMETER, THREADS_PART); monitoring(parameters); setProperty(Parameter.SYSTEM_ACTIONS_ENABLED, TRUE); parameters.put(PART_PARAMETER, SESSIONS_PART); monitoring(parameters); parameters.put(PART_PARAMETER, PROCESSES_PART); monitoring(parameters); TestDatabaseInformations.initJdbcDriverParameters(); parameters.put(PART_PARAMETER, DATABASE_PART); monitoring(parameters); parameters.put(PART_PARAMETER, CONNECTIONS_PART); monitoring(parameters); // il ne faut pas faire un heapHisto sans thread comme dans TestHtmlHeapHistogramReport // parameters.put(PART_PARAMETER, HEAP_HISTO_PART); // monitoring(parameters); } private void monitoring(Map<String, String> parameters) throws IOException, ServletException { monitoring(parameters, true); } private void monitoring(Map<String, String> parameters, boolean checkResultContent) throws IOException, ServletException { final HttpServletRequest request = createNiceMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/test/monitoring").anyTimes(); expect(request.getRequestURL()).andReturn(new StringBuffer("/test/monitoring")).anyTimes(); expect(request.getContextPath()).andReturn(CONTEXT_PATH).anyTimes(); expect(request.getRemoteAddr()).andReturn("here").anyTimes(); final Random random = new Random(); if (random.nextBoolean()) { expect(request.getHeaders("Accept-Encoding")) .andReturn(Collections.enumeration(Arrays.asList("application/gzip"))) .anyTimes(); } else { expect(request.getHeaders("Accept-Encoding")) .andReturn(Collections.enumeration(Arrays.asList("text/html"))).anyTimes(); } for (final Map.Entry<String, String> entry : parameters.entrySet()) { if (REQUEST_PARAMETER.equals(entry.getKey())) { expect(request.getHeader(entry.getKey())).andReturn(entry.getValue()).anyTimes(); } else { expect(request.getParameter(entry.getKey())).andReturn(entry.getValue()).anyTimes(); } } if (parameters.isEmpty() || JNLP_PART.equals(parameters.get(PART_PARAMETER))) { // dans au moins un cas on met un cookie final Cookie[] cookies = { new Cookie("dummy", "dummy"), new Cookie(PERIOD_COOKIE_NAME, Period.SEMAINE.getCode()), }; expect(request.getCookies()).andReturn(cookies).anyTimes(); } final HttpServletResponse response = createNiceMock(HttpServletResponse.class); final ByteArrayOutputStream output = new ByteArrayOutputStream(); expect(response.getOutputStream()).andReturn(new FilterServletOutputStream(output)) .anyTimes(); final StringWriter stringWriter = new StringWriter(); expect(response.getWriter()).andReturn(new PrintWriter(stringWriter)).anyTimes(); final FilterChain chain = createNiceMock(FilterChain.class); replay(request); replay(response); replay(chain); monitoringFilter.doFilter(request, response, chain); verify(request); verify(response); verify(chain); if (checkResultContent) { assertTrue("result", output.size() != 0 || stringWriter.getBuffer().length() != 0); } } private static void setProperty(Parameter parameter, String value) { Utils.setProperty(parameter, value); } }